芙蓉湖第一树莓果

RaspberryPi

@芙蓉湖第一树莓果

  • ❤️ Liked post in Friendly Gate-Friends' Links
    读书分享
    system Post #1

    If you like to befriend a friendly gate-friend, one way is to leave your blog here (by editing this post as long as you have reached trust level 1(青铜 (Bronze))). Below is some bootstrapping blogs aggregated from previous posts. You should put your blog's URL in angle brackets(< >) following the samples.

    URL Title Your Handle @xjtu.app Anything Else?
    https://npu.moe 瓜大萌 Err(:nullptr) 瓜大人萌萌哒学习交流平台
    https://axi404.top/ Axi404 @Forever 你好,我是阿汐,欢迎。
    https://ilovebread.buzz/ 主治医师李大华 @Lorange 何地才是樂土,讓競爭做指數
    https://ciallo.cv/ JuniorTree @Soyo34325 Ciallo~
    https://bocheng.me/ Bocheng Zou @uebian
    https://bertsin.pages.dev/ Bertsin @芙蓉湖第一树莓果 神秘小天地!
  • Yukinochyan Yukinochyan Post #1

    分享一些计算机专业的课程资料(课程作业,课程实验,部分往年题等),包括:计算机网络专题实验、编译器专题实验、嵌入式智能系统、软件定义网络、RUST语言程序设计、数据库系统、操作系统原理、软件工程、数字逻辑电路、形式语言与编译。

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #7

    确实
    在测试能否把用户名手动改成这个()
    可以改 但貌似也不会显示🤣

  • ❤️ Liked post in 幽默短片与抽象 meme 楼
    谈笑风生
    一只玉米人 玉米🌽 Post #119

    Image_1777022173390_317|375x500

  • stateless_trash_can 无状态垃圾桶 Post #2

    管理员辛苦了 :wave_gif:

  • IO IO Post #1

    前言

    本站使用的软件也运行了好多天了,目前各种小bug不断,但是好在没有什么致命的问题。
    为了帮助用户更好地理解本软件的开发情况,所以写一篇文章,介绍有哪些功能,数据是怎么迁移的。

    设计理念

    简单,好用
    侧重点:易用 > 易开发维护 > 拥有各种功能

    实现的功能

    本软件的设计,高度受Discourse启发。但不谋求实现Discourse的全部功能。

    Murmur: Modern Discussion Forum

    murmur is a high-performance, features-rich, Discourse/NimForum-style discussion forum. It is engineered with a hybrid SSR-First (Server-Side Rendering) architecture, delivering instant page loads and optimal SEO crawlers accessibility, while layering on real-time interactive widgets as progressive client-side enhancements.


    🛠️ The Tech Stack

    Murmur's architecture is divided into a high-performance web core, a relational database, and a specialized asset caching layer:

    • Web Core: SvelteKit 2 utilizing Svelte 5 Runes for robust state management.
    • Database & ORM: Drizzle ORM managing SQLite (better-sqlite3 driver) for synchronous operations.
    • Asset Performance: A custom caching proxy written in Rust using Axum (uploads-proxy).
    • Search Subsystem: SQLite FTS5 index combined with the sqlite-vec extension for vector operations, and @node-rs/jieba CJK tokenizer.
    • Real-time Features: Server-Sent Events (SSE) for pub/sub notifications, and Yjs text structures for wiki collaboration.
    • Styling: TailwindCSS v4 with Flowbite Svelte.

    🏛️ System Architecture Preview

    Murmur is designed to maximize speed by avoiding clientside rendering overhead during initial page loads.

    graph TD
        Client[Browser Client]
        SvelteKit[SvelteKit Node.js Server]
        SQLite[(SQLite DB / local.db)]
        Proxy[Rust Uploads-Proxy]
        Upstream[Upstream Assets Server]
        LLM[LLM API / Ollama / Gemini / OpenAI / Anthropic]
    
        Client -->|1. HTTP Page Request / SSE Stream| SvelteKit
        Client -->|2. HTTP Uploaded Files| Proxy
        Proxy -->|3. Cache Miss Fetch| Upstream
        Proxy -->|4. Save locally| Disk[(Local Uploads)]
        SvelteKit -->|5. Synchronous DB Queries| SQLite
        SvelteKit -->|6. Vectors & Generation| LLM
    
    1. Server-Side Rendering: SvelteKit processes the request, queries the SQLite database synchronously through the repository layer, compiles the page into static HTML, and responds.
    2. Client Hydration: The browser displays the HTML, downloads the JavaScript bundles, and hydrates components (e.g. Composer, Likes, Chat).
    3. Live Updates: An SSE connection is established to stream live updates (new posts, edits) to active tabs.
    4. Asset Offloading: The Rust uploads-proxy handles asset queries. If a file is cached locally on disk, it is served; otherwise, the proxy downloads it from the upstream server with retry logic, saves it locally, and serves it.

    📚 Documentation Index

    Below is the directory map of the Murmur system documentation. Click on any link to view detailed guides:

    ⚙️ [System Architecture & Scaling](file:///f/murmur/doc/architecture.md)

    • Detailed breakdown of the request-response lifecycle and hydration.
    • Rust uploads-proxy microservice design (thundering herd protection, atomic writes).
    • Horizontal scaling recommendations (reconciliation, moving from memory SSE to Redis pub/sub, object storage).

    Murmur: System Architecture

    This document describes the high-level architecture of Murmur, including the frontend framework, backend data flow, integration with external services, and horizontal scaling patterns.


    Technical Stack

    Murmur is built using a modern, lightweight JavaScript stack, layered with a high-performance Rust microservice:

    • Frontend / Meta-framework: SvelteKit 2 using Svelte 5 (Runes mode).
    • Styling: TailwindCSS v4 (CSS-first, no tailwind.config.js) & Flowbite Svelte components.
    • Database: SQLite (better-sqlite3 driver) wrapped with Drizzle ORM.
    • Search Vector calculations: SQLite extension sqlite-vec.
    • Search tokenization: @node-rs/jieba for CJK languages.
    • Real-Time Communication: Server-Sent Events (SSE).
    • Collaboration: Yjs text types synced stateless-ly over HTTP.
    • Assets Proxy: Custom Axum-based Rust microservice (uploads-proxy).

    Component Layout & Data Flow

    Murmur leverages Server-Side Rendering (SSR) by default to deliver HTML instantly to crawlers and users. Clientside Svelte components progressively hydrate the page to enable real-time messaging, infinite scroll, and rich editing.

    graph TD
        Client[Browser Client]
        SvelteKit[SvelteKit Node.js Server]
        SQLite[(SQLite DB / local.db)]
        Proxy[Rust Uploads-Proxy]
        Upstream[Upstream Assets Server]
        LLM[LLM API / Ollama / Gemini / OpenAI / Anthropic]
    
        Client -->|1. HTTP / SSE| SvelteKit
        Client -->|2. HTTP Static Assets| Proxy
        Proxy -->|3. Fetch cache miss| Upstream
        Proxy -->|4. Save locally| Disk[(Local Uploads)]
        SvelteKit -->|5. Synchronous Queries| SQLite
        SvelteKit -->|6. Vectors & Generation| LLM
    

    1. Request Lifecycle

    1. The browser requests a page (e.g., /t/slug/id).
    2. SvelteKit's routing resolves the path and calls the server-side load function (+page.server.ts), which queries the database synchronously via the repository layer (src/lib/server/repo.ts).
    3. SvelteKit renders the page as static HTML (SSR-first) and returns it.
    4. The client browser parses the HTML, displays it immediately, and fetches Svelte bundles to hydrate active widgets (e.g., the composer, emoji picker, likes).
    5. The client initiates a Server-Sent Events (SSE) connection to listen to live updates.

    Node.js & Rust uploads-proxy Integration

    User-uploaded attachments and legacy images are cached locally on disk. To prevent heavy Node.js threads from blocking on large file IO operations:

    • Node.js Server: Serves core HTML/JS payloads and handles API mutations.
    • Rust uploads-proxy: Serves files located under /uploads/. It listens on 127.0.0.1:4119 and handles file lookups.
      • Cache Hit: Serves the local file immediately using high-speed async file streaming via tokio-util.
      • Cache Miss: Downloads the asset from the configured upstream server (attempts up to 3 times, with a 2-second sleep duration between attempts), saves it locally, and serves it to the user.
      • Thundering Herd Coalesce: Employs a mutex and tokio::sync::Notify to block duplicate concurrent requests for the same missing asset, ensuring only one download request hits the upstream server.

    Real-Time Engine (SSE Pub/Sub)

    Murmur uses a single-process in-memory pub/sub pattern implemented in [events.ts](file:///f/murmur/src/lib/server/events.ts):

    • Route handlers or repository mutations call publish(topicId, event).
    • The Server-Sent Events endpoint [events/+server.ts](file:///f/murmur/src/routes/t/[slug]/[id]/events/+server.ts) subscribes to updates for a specific topic.
    • It streams JSON-LD chunk lines to the browser's EventSource instance.
    • The UI handles the event reactively to append new posts, update counts, or delete posts without page reloads.

    Horizontal Scaling Strategy

    Because SQLite and the SSE pub/sub system operate within a single process, horizontal scaling (running multiple instances of the Node.js process) requires:

    1. Database Layer: Replace the local better-sqlite3 instance with a replicated SQLite setup (such as LiteFS) or migrate Drizzle configuration to PostgreSQL.
    2. Pub/Sub Layer: Replace the in-memory singleton in [events.ts](file:///f/murmur/src/lib/server/events.ts) with a Redis or RabbitMQ pub/sub server. Route connections to the pub/sub interface so that messages publish across all Node server processes.
    3. Uploads caching: Ensure the uploads-proxy instances point to a shared directory (e.g., NFS, GlusterFS) or replace the local filesystem storage with an Object Store (like AWS S3) by modifying the SvelteKit file upload API.

    🗄️ [Data Model & Database Schema](file:///f/murmur/doc/data-model.md)

    • Relational schema definitions for SQLite.
    • Data design conventions (auto-increments, ISO-8601 timestamps, soft-deletions).
    • Database tables, relationships, and indices optimization.

    Murmur: Data Model & Database Schema

    This document details the database schema, SQLite conventions, and tables managed by Drizzle ORM in Murmur. The database schema is located in [schema.ts](file:///f/murmur/src/lib/server/db/schema.ts).


    Data Layer Conventions

    To simplify imports, backups, and exports from active Discourse installations, Murmur maintains the following database patterns:

    1. Integer Auto-increment Primary Keys: All tables use auto-increment integers. The system user is seeded with ID -1 (matching Discourse conventions).
    2. ISO-8601 Timestamps: Timestamps are stored as text (e.g. 2026-07-15T22:00:00.000Z) rather than SQLite Unix integers. They default to the current time via $defaultFn(() => new Date().toISOString()). This allows lexicographical sorting and matches Discourse CSV files.
    3. Booleans: Stored as integers (0 or 1) using Drizzle's integer(..., { mode: 'boolean' }).
    4. Post Rendering: Posts store both the raw Markdown text (raw) and the cooked sanitized HTML (cooked). Rendering is done via {@html cooked} without dynamic clientside compilation.
    5. Soft Deletions: Deleting topics or posts updates a deletedAt ISO timestamp column instead of deleting database rows.

    Database Tables

    Below is an overview of the Drizzle tables:

    1. users

    Represents forum members, administrators, and moderators.

    • id: Integer primary key (Auto-increment).
    • username: Unique username (Text).
    • name: Full display name (Text, nullable).
    • avatarUrl: URL of the user's avatar.
    • email: User email address.
    • githubId: Bound GitHub ID for SSO.
    • admin / moderator: Role toggles (Booleans).
    • trustLevel: Trust system ranking (0 to 4).
    • silencedUntil: ISO timestamp until which the user is banned from posting.
    • signatureRaw / signatureCooked: Markdown/HTML for post signatures.
    • chatGlobalMuted: Toggle to silence all chat badge notifications (Boolean).

    2. sessions & ssoSyncTickets

    Authentication sessions matching Oslo specifications.

    • sessions.id: SHA-256 hash of the session token.
    • sessions.userId: References users.id (on cascade delete).
    • sessions.expiresAt: Expiration timestamp.

    3. categories & categoryGroups

    Discussion categories which support nesting.

    • categories.id: Integer primary key.
    • categories.slug: Unique URL slug.
    • categories.parentCategoryId: Self-referential FK targeting the parent category.
    • categories.readRestricted: If true, restricts read permissions.
    • categoryGroups: Maps categoryId to groupId and defines permissionType (Read, Create, Reply).

    4. topics & posts

    Forum threads and post items.

    • topics.userId: Thread creator.
    • topics.bumpedAt: ISO timestamp updated on every reply to drive sorting.
    • topics.closed / topics.pinned: State flags.
    • posts.topicId: Parent thread.
    • posts.postNumber: 1-based sequential position within the topic (OP is 1).
    • posts.raw / posts.cooked: Markdown/cooked text.
    • posts.replyToPostNumber: Identifies the post being replied to.
    • posts.wiki: Toggle indicating if the post is editable by non-creators.

    5. postRevisions

    History of edits made outside the grace period.

    • postId: References posts.id.
    • userId: Author of the edit.
    • modifications: JSON string of modified properties (e.g. raw, cooked, title).
    • number: Version sequence number.
    • hidden: If true, hides modifications from normal users.

    6. postEmbeddings & topicRecommendations

    Vector semantic search embeddings and precomputed suggestions.

    • postEmbeddings.postId: References posts.id.
    • postEmbeddings.embedding: Raw vector float buffer (Float32Array).
    • topicRecommendations.topicId: References topics.id.
    • topicRecommendations.recommendations: JSON string list of recommended topic IDs.

    7. chatChannels, chatChannelMembers & chatMessages

    Real-time messaging channels.

    • chatMessages.channelId: Parent channel.
    • chatMessages.message / chatMessages.cooked: Raw/cooked text.
    • chatChannelMembers.muted: Individual channel muting preference.

    Schema DDL & Indices

    Drizzle automatically creates indices to optimize query performance and prevent database locks:

    • posts_topic_number_idx on (posts.topicId, posts.postNumber).
    • topics_category_bumped_idx on (topics.categoryId, topics.bumpedAt).
    • likes_post_user_unq unique index on (likes.postId, likes.userId).
    • topic_recommendations and post_embeddings map primary keys to their parent components to enable swift joins.

    ✍️ [Reply Composer, Drafts & Uploads](file:///f/murmur/doc/features/composer.md)

    • Composer UI controls (height adjustments, split ratios, fullscreen mode).
    • Local storage autosave and server-side syncing database logic.
    • Formatting toolbar helpers, emoji picker, and attachments uploads.
    • Kate-style whole-line keyboard shortcuts (Ctrl+X / Ctrl+C).

    Composer UI, Attachments & Draft Syncing

    This document describes the reply composer UI, clientside formatting shortcuts, the draft autosave engine, and the multi-file attachment pipeline.


    Composer Layout & Controls

    The composer component [Composer.svelte](file:///f/murmur/src/lib/components/Composer.svelte) is modeled after the Discourse editor. It resides in a sticky drawer at the bottom of the screen.

    +-------------------------------------------------------------------+
    |  [v] Drag Handle (Height)                                         |
    +-------------------------------------------------------------------+
    |  Title / Action Summary                      [ ] Full [ _ ] Min  |
    +-------------------------------------------------------------------+
    |  [ B ] [ I ] [ Link ] [ Quote ] [ Tt v ] [ + v ] [ Undo ] [ Redo ]|
    +-------------------------------------------------------------------+
    |  Textarea Input (Markdown)         |  Live HTML Preview           |
    |                                    |                              |
    |                                    |                              |
    |                                    |<---> Vertical Split Resizer  |
    +-------------------------------------------------------------------+
    

    Resizing Features

    • Height Resizing: Users can click and drag the top border handle. The chosen height is written to localStorage.
    • Split ratio Resizing: A vertical split bar sits between the editor and preview panels. Dragging it updates the split percentage dynamically.
    • Fullscreen mode: Toggles the composer to fill the viewport.
    • Minimization drawer: Minimizes the composer into a small, floating status bar at the bottom right.

    Rich Formatting Toolbar & Emojis

    1. Heading Selector (Tt)

    Inserts heading markdown (# to ####) at the cursor selection.

    2. Actions Selector (+)

    • Hide Details: Inserts a folding BBCode detail block:
      <details><summary>Summary</summary>
      
      
      content
      
      
      
    ``` - **Footnote**: Inserts inline footnote syntax (`^[footnote]`). - **LaTeX Math**: Inserts standard math symbols wrapper (`$x^2$`). - **Mermaid Flowchart**: Inserts standard Mermaid graphs template. - **Table / Date**: Generates formatted markdown tables or inserts local timestamps.

    3. Emoji Picker

    A custom Svelte 5 component [EmojiPicker.svelte](file:///f/murmur/src/lib/components/EmojiPicker.svelte) displays emoji categories. It supports text-based query filtering and inserts the selected emoji at the cursor.


    Kate-Like Whole Line Editing

    When typing inside the editor, Murmur supports KDE Kate-style shortcuts:

    • Ctrl+C (Copy): If no characters are selected (collapsed selection), copies the entire line containing the cursor (including the newline character).
    • Ctrl+X (Cut): If no selection is active, cuts the entire line and moves lines below it up.
    • Cursor Repositioning: After cutting, the cursor automatically snaps to the start of the next line, saving keystrokes.

    This logic is bound to the handleKeyDown function in the composer. It interacts directly with the browser's clipboard API and forces a tick update on Svelte's reactive states to maintain history.


    Draft Autosave & Database Synchronization

    To prevent data loss, the composer synchronizes drafts using a hybrid approach:

    sequenceDiagram
        participant Client as Browser Textarea
        participant Local as localStorage Cache
        participant API as /api/drafts/sync
        participant DB as SQLite drafts Table
    
        Client->>Local: Save drafts instantly on keystroke (Keydown)
        Client->>API: Periodic debounced save (Every 5 seconds)
        API->>DB: Write draft using compound key (userId + key)
        Note over API, DB: Last-write-wins merging by timestamp
    
    • LocalStorage: Serves as the primary cache to save text instantaneously.
    • Database Synchronization: Every 5 seconds (debounced), the client makes an HTTP POST request to /api/drafts/sync. It pushes drafts to the SQLite database, ensuring edits are preserved across devices.
    • Draft Disposal: Submitting a post deletes both the local storage key and the database row.

    Clipboard Paste & Attachment Pipeline

    The upload interface is triggered by clicking the paperclip icon or pasting an image directly from the clipboard into the editor:

    1. Upload Initiation: An async file reader creates a unique placeholder: [Uploading image.png...] at the current cursor position.
    2. Chromium List safeguard: Before beginning async processing, the file list is cloned into a static array. This prevents Chromium browsers from resetting the active input files when the input element value is cleared.
    3. API Upload: The file is sent via multipart POST to /api/upload. The endpoint validates files against allowed formats (e.g. jpg, png, gif, svg).
    4. Link Replacement: Once the API returns the permanent URL, the placeholder is replaced with the correct Markdown markup: ![filename|widthxheight](url).

    Codeblocks

    • auto-detection of codeblocks based on the first line of the codeblock.
    • mermaid flowcharts.
    • toggle line numbers
    • copy and full-screen buttons

    🔍 [Full-Text & Semantic Search (RAG)](file:///f/murmur/doc/features/search-and-rag.md)

    • SQLite FTS5 full-text indexing with Porter stemming.
    • CJK search query segmentation using Jieba tokenizer.
    • sqlite-vec semantic vector distance search pipeline.
    • RAG AI chatbot integration and context permission safeguards.

    Full-Text & Semantic Search (RAG)

    This document describes the search subsystem in Murmur, including full-text indexing, CJK segmentation, vector semantic calculations, and the RAG (Retrieval-Augmented Generation) chatbot.


    1. Full-Text Search Index (FTS5)

    Full-text search is powered by SQLite's FTS5 extension. During database initialization in [index.ts](file:///f/murmur/src/lib/server/db/index.ts), Murmur configures the virtual table search_index with Porter stemming to enable English word matching (e.g. "runs" matches "running"):

    CREATE VIRTUAL TABLE IF NOT EXISTS search_index USING fts5(
        title,
        content,
        topic_id UNINDEXED,
        post_id UNINDEXED,
        post_number UNINDEXED,
        user_id UNINDEXED,
        category_id UNINDEXED,
        created_at UNINDEXED,
        tokenize = 'porter unicode61'
    );
    

    CJK Query Segmentation (Jieba)

    Standard FTS5 tokenizers do not split Chinese, Japanese, or Korean (CJK) characters into individual words because they lack space boundaries.

    To solve this, Murmur intercepts search requests in [repo.ts](file:///f/murmur/src/lib/server/repo.ts) and parses queries using Jieba (@node-rs/jieba):

    1. RegEx Splitting: The query is split into CJK and non-CJK blocks.
    2. Segmentation: CJK blocks are parsed using jieba.cutAll() to extract words.
    3. FTS5 Wrapping: Extracted tokens are wrapped in double quotes and separated by spaces, converting the search into an implicit AND condition (e.g. 学习 Svelte becomes "学习" "Svelte").

    2. Semantic Search (sqlite-vec)

    Semantic search finds matches based on conceptual similarity rather than exact keyword matches. It uses the sqlite-vec extension to run vector operations inside SQLite.

    • Storage: Embeddings are stored as raw binary BLOBs (Float32Array) in the post_embeddings table to prevent thread blocking (converting JSON strings to arrays in JavaScript is CPU intensive).
    • Startup Migration: On startup, Murmur checks the database. If it finds legacy JSON string representations in the embeddings table, it converts them to binary buffers in batches of 500 rows.
    • Query Resolution: Employs a cosine similarity calculation in SQLite:
      SELECT post_id, vec_distance_cosine(embedding, ?) AS distance
      FROM post_embeddings
      ORDER BY distance ASC
      LIMIT 20;
      

    3. RAG Chatbot Integration

    When a user runs a search query, Murmur displays a RAG chatbot assistant panel next to the search results:

    +-----------------------------------------------------------------+
    | Search Results                     |  🤖 Chatbot Reply          |
    |------------------------------------|----------------------------|
    | 1. Topic: How to run Murmur        |  To run Murmur, execute:   |
    |    By user1 - "Run pnpm dev..."    |  `pnpm dev`. Refer to      |
    |                                    |  /t/murmur/1 for details.  |
    | 2. Topic: Production Setup         |                            |
    |    By user2 - "Compile build..."   |  [ AI thinking indicator ] |
    +-----------------------------------------------------------------+
    

    LLM Streaming client

    The server client in [chatLlm.ts](file:///f/murmur/src/lib/server/chatLlm.ts) streams responses from different providers:

    • Ollama: Parses line-by-line NDJSON chunks.
    • Gemini / OpenAI / Anthropic: Parses Server-Sent Events (SSE) data streams.

    SSE Stream Synthesis

    When a search is requested, the search API endpoint [stream/+server.ts](file:///f/murmur/src/routes/api/search/stream/+server.ts) initiates an SSE stream:

    1. It queries FTS5 and semantic databases for matches.
    2. Results are formatted as Markdown context blocks.
    3. It asks the LLM to summarize the findings and include links to the matched topics (e.g. /t/slug/id/post_number).
    4. It streams response tokens to the client browser via ai_answer_chunk events, which are compiled and rendered in the UI using markdown-it.

    4. Privacy & Permission Filtering

    To prevent information leaks (e.g., exposing private messages or restricted categories in search results or AI summaries):

    • Permission Checking: The search service retrieves category permission rules via getPermittedCategoryIds(user).
    • Pre-filtering: Topics and posts belonging to restricted categories are filtered out of the results before the data is cached or sent to the LLM.
    • RAG Security: The LLM context contains only the results the user has permission to read.

    ✍️ [Revisions & Wiki Editing](file:///f/murmur/doc/features/revisions-and-wiki.md)

    • Post edit revisions, grace period overrides, and modifications storage.
    • Myers split-diff comparison modal and revision rollbacks.
    • Wiki post permissions and stateless Yjs collaborative sync protocol.

    Revisions, Wiki Posts & Yjs Collaborative Editing

    This document explains the version control system for post edits, wiki post privileges, and the collaborative Yjs document synchronization engine.


    1. Post Revisions System

    Murmur tracks the history of changes made to posts and topic details (titles and categories) over time.

    Grace Period & Versioning

    • Editing Grace Period: Managed by the editing_grace_period site setting. If a user edits a post within this threshold (e.g. 5 minutes) after creation, modifications are overwritten without creating a new revision.
    • Revision Capture: Edits made after the grace period increment the post's version (and publicVersion) and save the differences to post_revisions.
    • Modifications Storage: Differences are stored as JSON-serialized change objects containing the previous values of modified fields:
      {
      	"raw": ["Old post raw markdown", "New post raw markdown"],
      	"title": ["Old topic title", "New topic title"]
      }
      

    2. Visual Diff Comparison Modal

    When a post contains revisions, a clickable edit counter (e.g., ✍️ 2) is displayed next to the post's timestamp. Clicking it opens the [PostRevisionsModal.svelte](file:///f/murmur/src/lib/components/PostRevisionsModal.svelte) component:

    • Myers Diff Algorithm: Compares line-by-line differences in raw markdown or HTML tags.
    • Cooked HTML Preview: Toggles to render the formatted HTML output.
    • Reversion: Users with edit permissions can click the "Revert" button to roll back the post to a chosen revision.
    • Visibility controls: Staff members (administrators and moderators) can toggle the visibility of individual revisions to hide sensitive information.

    3. Wiki Posts

    Wiki posts allow collaborative editing by members of the community rather than just the author.

    • Wiki Toggle: Staff members can convert any post into a wiki post.
    • Permissions: Admins can configure the minimum user group or trust level required to edit wiki posts (defaults to staff and trust_level_2 users).
    • Indicators: Displays a wiki badge next to the post to show users they have permission to edit it.

    4. Stateless Yjs HTTP Sync Protocol

    To enable concurrent collaborative editing without keeping persistent WebSocket connections open, Murmur uses a stateless HTTP synchronization protocol:

    sequenceDiagram
        participant Client as Browser Editor
        participant Server as /api/posts/[id]/wiki-sync
        participant DB as SQLite DB
    
        Client->>Server: Send stateVector (base64) & update (base64)
        Server->>DB: Fetch post yjsState BLOB
        Server->>Server: Apply client update to Y.Doc
        Server->>Server: Compute diff using client stateVector
        Server->>DB: Save updated Y.Doc buffer to yjs_state
        Server->>Client: Return update (base64) & merged text
    

    Protocol Steps

    1. Initiation: The editor initializes a Yjs document (Y.Doc) and extracts the text content.
    2. Synchronization Request: The client sends an HTTP POST request to /api/posts/[id]/wiki-sync containing its local Yjs state vector and updates, encoded in base64.
    3. Server Merge:
      • The server loads the post's current yjsState from SQLite.
      • It instantiates a server-side Y.Doc and applies the database state.
      • It applies the base64 update received from the client.
    4. Calculations: The server computes the missing updates for the client using the client's state vector.
    5. DB Update: If the merged text differs from the post's current content, the server runs editPost() to update raw/cooked columns and saves the new Yjs state buffer.
    6. Response: The server returns the missing updates and the updated text to the client.

    💬 [Real-Time Chat & Badges](file:///f/murmur/doc/features/chat.md)

    • Public channels, direct message groups, and message management.
    • Svelte 5 runes unread badge calculation and global/channel muting.

    Real-Time Chat & Unread Badge system

    This document describes the real-time chat subsystem in Murmur, including channels, user privileges, message edits, and the Svelte 5 runes unread badge system.


    1. Chat Channels & DM Rooms

    Murmur includes a built-in real-time chat workspace. It supports two channel types:

    • Public Channels: General channels accessible by all registered members.
    • Direct Messages (DMs): Private chat rooms created between two or more users.

    2. Real-Time Message Flow

    The chat interface streams updates in real time using Server-Sent Events (SSE):

    sequenceDiagram
        participant ClientA as Sender Browser
        participant API as /api/chat/messages
        participant DB as SQLite DB
        participant SSE as SSE Stream Channel
        participant ClientB as Receiver Browser
    
        ClientA->>API: POST send message
        API->>DB: Write message to chat_messages
        API->>SSE: Publish message event
        SSE->>ClientB: Stream JSON event
        Note over ClientB: Append message to UI
    

    Message Modifications

    Users can edit or delete their own messages after they are sent. Moderators and administrators can edit or delete any message. Modifying a message updates the database and publishes an update event over SSE to sync all active clients.


    3. Svelte 5 Runes Unread Badge System

    To manage notification badges dynamically across the app, Murmur uses a client-side global state store powered by Svelte 5 runes:

    • State Store: Defined in a client-safe state module. It tracks active channels, members, read states, and global mute preferences.
    • Dynamic Badge calculations: Unread counts are computed using $derived values:
      // Simplified logic
      const unreadCount = $derived(() => {
      	if (globalMuted) return 0;
      	return channels
      		.filter((c) => !c.muted)
      		.reduce((sum, c) => sum + (c.messagesCount - c.lastReadMessageId), 0);
      });
      
    • Real-Time Updates: When a new message event is received via the SSE connection, the client-side store increments the channel's message count. The UI updates the unread badge automatically.
    • Read State Sync: Reading a channel updates the client-side state and sends an API call to save the lastReadMessageId in the database, syncing the read state across devices.

    4. Muting Preferences

    To prevent notification fatigue, users can configure their alert preferences:

    • Channel Muting: Users can mute individual channels. Muted channels do not trigger badge alerts or red dot indicators.
    • Global Muting: Users can enable global muting in their profile settings. This silences all chat notifications across the site.

    💻 [Developer Guide & Conventions](file:///f/murmur/doc/developer-guide.md)

    • Coding standards (runes, TailwindCSS v4, synchronous queries, types).
    • File-based routing structure.
    • ESLint and Prettier code formatting standards.

    Developer Guide & Conventions

    This document outlines the coding standards, repository layout, and development guidelines for developers working on the Murmur project.


    1. Project Conventions

    Svelte 5 Runes Mode

    • Murmur uses Svelte 5 runes. Use $props(), $state(), $derived(), and $effect() for state management.
    • Do not use legacy Svelte APIs (such as export let, $:, or store.subscribe).
    • The compiler options are inlined in the vite.config.ts file under the Svelte plugin configurations.

    Database Layer

    • SQLite database operations run synchronously.
    • Do not await database queries: Drizzle queries use .all(), .get(), and .run() synchronously.
    • Implement database mutations in [repo.ts](file:///f/murmur/src/lib/server/repo.ts). Do not write inline database queries in routes or page endpoints.

    Code Separation

    • Server-Only Code: Any logic placed under src/lib/server/** is excluded from browser bundles.
    • Shared Types: Clientside modules cannot import server code. Shared structures must be defined in [types.ts](file:///f/murmur/src/lib/types.ts).

    Styling & CSS (TailwindCSS v4)

    • TailwindCSS v4 is integrated as a CSS-first design tool. There is no tailwind.config.js.
    • Configurations, theme overrides, and custom fonts are managed in [layout.css](file:///f/murmur/src/routes/layout.css) using CSS variables.

    2. Directory Routing Structure

    The routing layer uses standard SvelteKit file-based routing under src/routes/:

    • / : Landing page displaying latest topics.
    • /c/[slug]/[id] : Topics filtered by category.
    • /t/[slug]/[id] : Topic thread displaying posts and reply forms. Includes SSE streaming listeners.
    • /new : Full-page composer workspace.
    • /login : Authentication page (GitHub SSO & dev login).
    • /admin/settings : Dashboard for administrators to configure site settings.
    • /sitemap.xml : Dynamic sitemap generation for web crawlers.

    3. Formatting Standards

    Code styling is enforced using Prettier and ESLint:

    • Indent: Tabs.
    • Quotes: Single quotes (').
    • Trailing Commas: None.
    • Line Width: 100 characters.

    Verify formatting using the formatting scripts before submitting changes:

    pnpm lint      # Checks linting and formatting compliance
    pnpm format    # Automatically formats files
    

    🛠️ [Operations & Maintenance Scripts](file:///f/murmur/doc/scripts.md)

    • Standalone operational scripts under scripts/ (import tools, reindexing, post rebaking, and embedding calculations).

    Data Migrations & Operations Scripts

    This document details the standalone command-line scripts located in the /scripts/ folder. These scripts are run using tsx (e.g. pnpm tsx scripts/rebake-posts.ts).


    1. Data Imports & Exports

    [import_discourse_csv.ts](file:///f/murmur/scripts/import_discourse_csv.ts)

    Imports forum databases from a Discourse CSV export.

    • Workflow: Parses user profiles, categories, topics, and posts.
    • Parsing: Translates Discourse emojis, system formatting, and image layouts into Murmur equivalents.
    • Rebaking: Automatically runs the HTML cooking function on all imported posts to populate the cooked column.

    [import_post_revisions.ts](file:///f/murmur/scripts/import_post_revisions.ts)

    Reads historical edit logs from a Discourse CSV export and populates the postRevisions table.

    • Workflow: Converts Discourse YAML modifications into JSON and links them to their respective post IDs.
    • Recalculation: Adjusts version and publicVersion sequences on affected posts.

    2. Topic recommendations & Embeddings

    [embed-posts.ts](file:///f/murmur/scripts/embed-posts.ts)

    Generates vector float embeddings for search calculations.

    • Workflow: Identifies posts that do not have embeddings in the post_embeddings table.
    • Generation: Calls the configured LLM API (e.g. Ollama, OpenAI) to generate vector embeddings.
    • Persistence: Writes vector embeddings to the database as binary buffers.

    [generate-related-topics.ts](file:///f/murmur/scripts/generate-related-topics.ts)

    Computes topic similarity recommendations.

    • Workflow: Calculates vector distances between topic posts.
    • Storage: Saves the top 50 matches for each topic as a JSON list in topic_recommendations.

    3. Maintenance & Optimizations

    [rebake-posts.ts](file:///f/murmur/scripts/rebake-posts.ts)

    Re-processes post content using the Markdown compiler.

    • Usage: Run this script after modifying markdown parser rules, BBCode preprocessors, or HTML sanitization options to update all compiled posts.

    [rehash-compress-replace.ts](file:///f/murmur/scripts/rehash-compress-replace.ts)

    Compresses and optimizes uploaded assets.

    • Workflow: Compresses images on disk, updates their URLs, and updates file paths in raw and cooked post content.

    [reindex.ts](file:///f/murmur/scripts/reindex.ts)

    Rebuilds the virtual FTS5 search index.

    • Workflow: Wipes search_index and indexes all posts in the database.
    • CJK splitting: Uses Jieba to segment Chinese, Japanese, and Korean content.

    ⚡ Quick Start

    1. Prerequisite Installations

    Ensure you have Node.js 26+ and pnpm 11+ installed. If you plan to run the uploads proxy or semantic search, make sure cargo (Rust toolchain) and SQLite are available.

    2. Development Setup

    Clone the repository and install dependencies:

    pnpm install
    

    Configure your environment variables:

    cp .env.example .env
    

    Modify .env to define:

    • DATABASE_URL: Path to your database file (defaults to local.db).
    • ORIGIN: The server domain (e.g. http://localhost:5173).
    • GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET: OAuth credentials.

    Initialize and seed the database with mock categories, users, and topics:

    pnpm db:push
    pnpm db:seed
    

    Start the Vite development server:

    pnpm dev
    

    Open /login and use the Dev Login button to authenticate as any user without configuring GitHub OAuth.


    📁 Repository Layout

    • src/routes/ - SvelteKit routing layer (pages, endpoints, SSE streams).
    • src/lib/ - Shared code, UI components, and state modules.
    • src/lib/server/ - Server-side modules (database pools, auth Oslo, markdown cooker, search caches).
    • scripts/ - Standalone tools (data imports, re-indexing, embedding pre-calculations).
    • uploads-proxy/ - Rust Axum asset cache proxy server.
    • doc/ - System documentation markdown files.
  • ❤️ Liked post in [记录贴] 26年西湖暑研
    谈笑风生
    Soyo34325 Soyo34325 Post #9

    07-04

    昨天进的实验室,然后办了入校!云栖校区比我预期中的要小的很多很多,比起大学更像是一个小的研究所,来的第一天就有点绝望啊,因为周围真的好偏!感觉完全没啥玩的,下午入校找到工位之后就开始搬砖了,因为之前在线上的时候跟过一部分,周围比较好的是KFC和麦当劳都有!麦金卡续起来

    IMG_1481|375x500

    IMG_1532|375x500

    今天到看房,和中介约好的,看的第一间房真的是惨不忍睹,原本是和实验室的同门合租,但是我发现那个房子有间屋子没有窗户,楼下是垃圾回收站,味道很大!但是短租真的超级难找,原本找到的一个梦中情房是上下楼的,下面是电视,然后上面是睡人的,但是人家不肯租,只能11个月签合同,后来找到个类似于酒店的那种公寓式的,价格贵了点,地方小了点,卫生还需要自己打扫一下,我想着要不要请一个阿姨来帮忙打扫一下,类似京东家居这种?

    下午还到宜家!师兄说他来杭州1年了还不知道宜家在哪里!买了枕头、床单、空调被等等,感觉好幸福,正好还在住酒店,就把新买的床单借用酒店的洗衣机洗了一下,再烘干

    IMG_1530|375x500

  • IO IO Post #28
    I_Love_ZJU:

    发现同时选择多张图片上传 实际上传的只有第一张图片 每次都得重新选择有点不方便🫠

    已修复。我之前用Firefox没遇到过这个bug,用Chromium可以复现。

    芙蓉湖第一树莓果:

    定义几个模板,例如2×2 grid,让用户选择

    当前grid模式是为了更好地展示多张图片。目前当上传多张图片,或者多张图片连在一块时,会自动插入在两头插入

    [grid mode ="tile"]
    [ /grid]
    

    ,从而通过tile/slide展示多张图片。如果需要连续的布局,可以修改为[grid mode="off"]

    看来可以添加对mode="2x2"mode="axb"这种允许用户自定义的参数的解析。(已实现)

  • IO IO Post #25
    I_Love_ZJU:

    以及 不知道本站是否支持选中其他发言的部分内容进行引用回复的功能()

    已添加Quote/Copy Quote的功能。

    I_Love_ZJU:

    但是我刚刚发现同一个帖子有多个spoiler 内容不能同时显示 点开一个其他的就会隐藏?

    这个只是和Discourse的行为不一样,我觉得当前的行为也能接受。

    芙蓉湖第一树莓果:

    xjtu.app的表情似乎并没有完全迁

    目前试验了一下,emoji-picker里自定义部分的图片都能正常加载。

    芙蓉湖第一树莓果:

    我們可能觉得有趣的内容 中的链接需要指向.men站点(我們可能觉得有趣的内容这个帖子原本是门友都可以编辑的帖子,现在门友并没有对应的编辑权限)。

    目前登录.app或.men中的任一域名,登录状态都会被同步到另一个域名,所有功能全部相同,只是网络流量不过/过CDN的区别。
    为了防止在不同的域名间切换,我們可能觉得有趣的内容 中的absolute URL已被手动改成了relative URL.

    make post wiki 是个好功能,不过它依赖于:

    • post revisions management,方便看到谁改了什么,以及回滚
    • trust level system,当前把Discourse的等级迁移过来了,但是自动升级的机制比较复杂,还涉及到post read numbers / read time / login days 等的统计
    • collaborative edit:类似于云文档多人同时协作编辑,可以用yjs. 否则如果两个人同时修改,容易产生冲突。
  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #167

    读完了包法利夫人 感觉里面对人类情感和欲望的描写以及走向毁灭的过程非常真实 甚至很符合当今现实
    今天开始二刷呼兰河传 第一次看是小学的时候 评价是它有些内容不太适合小学生看 里面有一些关于封建迷信的情节在我幼小的心灵中留下了不可磨灭的印象
    因为喜欢《记忆中的玛妮》这部电影 所以还找到了原著(叫做 when Marnie was there) 也是今天开始阅读🥰
    最近考完几天就这样开始沉迷文学 期末考请永远不要出分 或者不要给我带来惊吓啊啊啊

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #168

    今天和朋友回高中看老师了
    皮革记录
    IMG_9162|666x500

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #169

    下载了一本关于Borgia家族历史的书(The Borgias: the hidden history) 主要是想看文艺复兴时期的权谋斗争(bushi)
    没找到中文版于是只能看英文的 现在还停留在第一代Alonso Borgia的故事
    这本书比较好的一点是它会有很详细的背景信息介绍 方便我理解

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #170

    打算开始看《红猪》
    《呼兰河传》看完了 接下来可能会看《生死场》 但目前还没开始
    今天早上把《他改变了中国》剩下的一小部分读完了

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #171

    今天开始看Rodrigo Borgia的故事 估计要看很久()

  • Xrystal-line 羽流弦ノ迹 Post #175

    高中的时候我们语文老师也推荐我们看这部电影,北野武老师真的好幽默 😆

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #178

    抚顺战犯管理所旧址
    看过好几次《末代皇帝》电影 也读过《我的前半生》和《溥杰自传》 一直都很想去这里看看
    和电影里的场景看起来很像 好评

    IMG_9446.jpeg|666x500
    IMG_9424.jpeg|666x500
    IMG_9414.jpeg|666x500
    IMG_9430.jpeg|666x500

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #162

    今天一直在下雨 尤其是下午考完后 遇上晚高峰还打不到车 对交大的杀意又一次达到顶峰

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #157

    今天看了好久的鹅腿阿姨(变质鸭腿阿姨)的新闻
    感觉好难以置信 之前好几年那么多人吃到发绿的鸭腿也都被糊弄过去了 但是在国贸那边居然没过一周就被举报了

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #156

    前天晚上梦到查这学期考试的科目的成绩 被吓醒了
    昨晚过了好久才睡着
    应该是因为压力太大了 期末周坏 交大该杀

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #24

    原先设置了spoiler的内容在这里似乎无法点开看到具体内容?望修复🥹
    updt:抱歉我误会了!这个问题不存在

    但是我刚刚发现同一个帖子有多个spoiler 内容不能同时显示 点开一个其他的就会隐藏?

    以及 不知道本站是否支持选中其他发言的部分内容进行引用回复的功能()

  • IO IO Post #18

    Issue tracking

    进度栏,这个还真不太好实现,当前的远远没有Discourse完美

    发现贴表情的时候 pig2的动图只能显示🐖的图案 但自己发帖可以正常显示

    reactions: pig2 gif are not animated
    the url hould be </uploads/image/a5/52/a552de2017382634e9bb9c81e663be3a8c3e4cca7a07c0a683cc44788464e62b.avif>
    shows as an static pig emoji,
    which is unlike wave_gif which the url is kept

    群聊的文字配色或许可以优化一下… dark模式下别人发的文字有点难以辨认 light时自己发的文字看不清

    improve basic topic moderation functionality
    should allow mod and admin to edit any topic title, delete topic, close topic,

    allow configure max number of posts in topic, auto close topic after reach this limit

    https://meta.discourse.org/t/discourse-moderation-guide-part-2-managing-users/406265
    https://meta.discourse.org/t/discourse-moderation-guide-part-3-managing-content/406266

    new user cannot access the general chat, which should be available to all users. and also allow users to mute channels/chats.

    use IndexedDB to cache content to prevent return-to-home-page lag

    composer: Ctrl+X/C when nothing seletect should cut/copy whole line

    reply-to and replied-by indicator in post

  • IO IO Post #22

    超出屏幕范围和图片无法上传问题已修复

  • i13l
    TwlnfuSprig TwlnfuSprig Post #267

    换新ui了好怪,之前的一些图图也消失了

    不过倒是蛮稳定了

  • 周末 😀 Post #546

    最近在玩胶卷,在想 搭一个胶片的小app用于同好交流整理自己拍过的卷、ai调色、重构图、及一些胶片知识(?交流的部分可以类似于discourse
    其实是我想学一下调色并且感觉自己的构图不够好,调色还需要积累构图也许未来会买点便宜的黑白卷多扫街练习!
    并且我希望可以整合目前胶片爱好者所缺少的一些助手,比如我拍半格但扫描是两张扫在一起的需要手动裁成两张。比如拍胶卷最好的观看方式是按拍摄顺序排成一行因为有时间流逝的感觉。比如胶片后期调色有一定门槛,如果可以优化设置为一键调色会更方便。比如胶卷保存最好可以每卷都加一个地址、时间、拍摄的相关参数(ISO/快门速度/光圈大小等等)、这卷胶片的扫描机器以及每张的备注可以记录每张胶片背后的故事(每一次让我按下快门一定是有原因的)

    我现在还只是一个想法,但似乎真的缺少针对胶片爱好者的圈子。大部分的讨论都在xhs,有一些这些零零散散的信息。是否有必要?会有多少用户?

    反正我需要做一个网站交作业,做个demo正好。

  • 一只玉米人 玉米🌽 Post #1

    玉米人是今年数院研一新生,最近几天涉及到自己制定培养方案的问题,比较迷茫。想在此咨询門友学长学姐们一些问题。🥺尤其是路过的数院与电信学部的学长学姐。🥹 当然也欢迎广大門友畅所欲言!(这是一个讨论帖)

    一些比较宽泛的问题

    1. 研究生是否应该选尽可能水的课(考核方式尽可能是“考察”),无论其是否与自己方向相关?

    2. 今天在系统上,我注意到,有些课和本科期间专业课比较像(授课老师、大纲都差不多)。对于这种已经学过的、难度一般的、考核为考试的课,是否值得选?

    3. 研究生期间的奖学金评比标准和本科差不多吗?还是智育和德育(论文、竞赛、社会实践等等)的加权吗?如果是加权的话,大致比例和下图一样吗?

    4. 想拿学业奖学金的话,是否还需要卷绩点(我听说研究生阶段的成绩为优、良、中、合格、不合格)?在评定奖学金的时候,如果没有科研成果,是不是整个科研部分的得分就是 0?这是否意味着,如果没有小成果,就无法拿奖学金?😰(听说导师在研二下之前好像只允许投A会,不让投其他较水的会/刊)

    image.png|690x104

    想问数院学长学姐

    下面是我准备圈定的培养计划之本院课程池子。
    请问其中有哪些是课水分高的好课呢?其中有事多分低的烂课吗?请问其中有您上过的课吗?考核方式具体是什么呢?
    如果您愿意告知,玉米人会不胜感激!🥰

    课程名称 课程类型 学分 学时 学期/考核方式
    非线性分析 必修课 3 64 秋季(考试)
    凸分析与优化理论 必修课 3 48 春季(考试)
    黎曼几何 必修课 3 64 春季(考试)
    --- --- --- --- ---
    Stochastic Differential Equation with Application 选修课 2 32 秋季(考试)
    Modern functional analysis 选修课 2 32 秋季(考试)
    机器学习 选修课 2 32 秋上(考试)
    计算方法 选修课 3 84 秋季(考试)
    反散射简介 选修课 2 32 秋季(考查)
    深度学习与人工智能 选修课 2 32 秋下(考查)
    机器学习的数学理论及前沿进展选讲(AI进阶) 选修课 2 32 秋下(考查)
    人工智能辅助科研写作的实践与应用(AI进阶) 选修课 1 16 秋上(考查)
    运筹学方法 选修课 2 32 春上(考试)
    文本分析与图像处理 选修课 2 40 春上(考试)
    随机过程 选修课 2 32 春季(考试)
    矩阵分析与矩阵计算 选修课 2 32 春上(考试)
    大数据分析与处理方法 选修课 2 40 春上(考查)
    机器学习的编程设计 选修课 2 32 春季(考查)
    非参数统计推断 选修课 2 32 春季(考查)
    生成式人工智能(AI实践) 选修课 2 32 春下(考查)

    想问电信学部学长学姐

    下面是我准备圈定的培养计划之跨院AI前沿课程池子。
    请问其中有哪些是课水分高的好课呢?其中有事多分低的烂课吗?请问其中有您上过的课吗?考核方式具体是什么呢?
    如果您愿意告知,玉米人会不胜感激!🥰

    课程名称 课程类型 学分 学时 学期/考核方式
    对抗性机器学习与人工智能安全(AI进阶) 选修课 2 32 秋下(考试)
    大数据与深度学习及其应用(AI进阶) 选修课 2 32 春上(考试)
    Artificial Intelligent Generative Content (AIGC) and image processing(AI进阶) 选修课 1 16 春上(考查)
    大模型技术原理及应用(AI进阶) 选修课 2 32 春下(考查)
    强化学习及其前沿(AI进阶) 选修课 2 32 春下(考查)
  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #172
    紫金港第一皮革<・)))><<:

    因为喜欢《记忆中的玛妮》这部电影 所以还找到了原著(叫做 when Marnie was there) 也是今天开始阅读 🥰

    快读完了 感觉吉卜力的电影版更好看(虽然我平时一般原著和电影都是选择原著的)
    原著的文笔个人感觉一般 然后吉卜力的电影版改编后情节更加流畅 而且有一些更优美的细节

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #173

    想放点读书划线的内容 但都在电子书上懒得导出()

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #174

    在看菊次郎的夏天 里面的天使风铃的翅膀形状给我的第一反应竟是浙大求是鹰 瞬间出戏
    IMG_2890|690x479

    今天看完了 很推荐这部电影(尤其是配乐很好听)

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #176

    开始二刷安娜卡列宁娜 虽然不知道要看多久 在阅读包法利夫人之后二刷可能会有更深的感受🤔

    接下来会外出旅游and皮革 可惜成绩还没出完 不安desu

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #177

    旧的discourse论坛是没了吗 哀悼😭
    这几天去辽宁游玩 皮革快乐(除了有次吃锅包肉被香菜偷袭)
    去了西塔 堪比一只皮革的朝圣 看着满街的韩料真的很快乐 西塔韩百也很好逛 有在hk逛超市的感觉(虽然东西没那么多但也不少了)
    IMG_9469.jpeg|666x500

  • Xrystal-line 羽流弦ノ迹 Post #3

    西安这一周以来天天35°C+,即使中间有个晚上下了暴雨
    没带伞的我在实验室被堵到4点钟

    今天早上起来看到是高温红色预警,下午又来了暴雨大风黄色预警:magic_wand_innocent:

    东南沿海最近都在讨论台风
    不知道门友所在地的天气如何?

    西安市区依旧高于往年均值6°C左右
    西安市区依旧高于平均值6°C左右

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #4

    来自sjtu 但真诚地认为交大该杀
    (目前主要是在这里发闲言碎语了 而且人少了几乎是单机模式)

  • Ti Post #3

    爱来自刚从xjtu毕业的fudan新生😋

  • hoist hoist Post #2

    挑着看看指定的精华帖。这部分还是比danxi好的

  • raccoonbk Raccoonbk Post #1

    rt。想问问这个上面XJTU和SJTU的uu们都有吗?
    祝愉快!

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #165

    总算可以上门了
    沉迷小说
    昨天二刷了牛虻 一刷是因为保尔柯察金 二刷是因为基督山伯爵里面不经意的一句话涉及了牛虻的关键情节
    结局给我的印象极其深刻 完全是恨海情天 强烈推荐! 我到现在还无法使自己的精神恢复平静(好处是在想这个书 暂时没那么担心出分了)
    为了避免剧透 就暂且不放具体的内容了

    今天开始首次阅读包法利夫人 目前读到了第二部 对人物情感的描写也很精彩

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #166

    昨晚本来想找浮士德的纸质书进行一个二刷的尝试 但发现了高一时购买的法国文明史 遂开始阅读 虽然目前还没走出中世纪的内容🤣
    今天也在继续阅读包法利夫人 但还是会时不时想起牛虻的结局 真的太痛了😭

  • ❤️ Liked post in 水·暑期狂想曲
    谈笑风生
    setsuna 做回自己世莉架 Post #1

    水一帖。

    不知道门友对暑日和假期有什么印象,又有什么规划。成长在中国火炉的我,记忆里的夏日总是无尽灿烂的烈日倾盆而下,裹覆着大地和生灵万物。从江边袭来的氤氲水汽,锁住已经被粘腻汗水打湿的毛孔。身体的热量无处散发,积郁在胸腔和脑腔。热,真的很热,人像是蒸笼里的螃蟹,被炙烤、汽蒸着心神,被折磨、剥夺理智。

    但我喜欢夏天。冬天太阴郁,春天和秋天太短暂。只有夏日有明媚的蔚蓝色天空。深沉的蓝色好像windows7的壁纸一样纯净。还有西瓜,夏季给人类的馈赠,没有比西瓜更好吃的水果,多汁清甜,但不酸不腻,只是我妈不允许我多吃,避免我拉肚子。

    夏天还有一年中最长的假期。暑假里我有时间拜访舅舅,和表弟在老家漫山遍野地乱跑。折下树枝,然后去山另一边的小卖部买彩纸做风车;晚上睡在一起但比力气摔跤到半夜;拿把柴刀砍树,制作两把圣剑然后决斗... 种种行为大人们看来幼稚,但给我们无尽快乐。遗憾的是年龄渐长,两人没有了共同话题。我还是当年那般幼稚,但他已经长大成熟了。

    暑假里还会和同学相约,每日一同沿江骑行,到区图书馆看书、游戏。家乡的河流真的非常、非常美丽,笔直宽阔的滨江路沿着江水延伸,沿江一侧是茂密的树林,另一侧是缓缓的山体和防滑坡墙,山脚的洋房,一所大学和区图书馆。我和同学在午后两点顶着四十度的高温骑车到图书馆,在图书馆看书、打游戏。我喜好阅读科幻文学,在图书馆里看完了刘慈欣所有的小说,长篇如三体、球闪,短篇如山、赡养上帝等(超新星纪元的各版本还是在网上才阅读完全);因为没有电话卡,连不上网,我们只能玩平板上的单机游戏。桥梁建筑(poly bridge)成为我们的最爱,两个人交替提出改进意见,优化桥梁设计直到通关。我们至今仍然保持联系,但他在北京上学,所以平时无法见面。

    人总是会美化经历,抛却记忆中的不快,塑造美好的回忆,但曾经的快乐的确真实。

    日子总不会太好,也不会太差。我是贪婪的物种,即使未来会创造新的快乐回忆,但因为过去的快乐无法重现,我也分外怀念那些逝去的日子。

    这个暑假,机械专业实习和重修结束后,我又要返回家乡了。这次我期待着家里肥美的狸花猫,想狠狠撸它;期待着能用攒的钱买一台无人机,在镜头里俯瞰我的家乡;期待着看完《计网自顶向下》后开始学习计组...

    最后,祝福所有门友暑假快乐,度过一个难忘的快乐夏天!

  • i13l
    TwlnfuSprig TwlnfuSprig Post #266

    image|690x295

  • i13l
    TwlnfuSprig TwlnfuSprig Post #265

    😗熟悉的人都彻彻底底的毕业了,还有一些小小登)
    可惜po没机会也做不到去合影,今天在干别的事情

    好像打什么字都是感伤了,虽然是熟悉的人但po的分量也是个过客罢了,只留困在回忆里的po

  • ❤️ Liked post in xjtuer 的实盘经历记录
    谈笑风生
    Xrystal-line 羽流弦ノ迹 Post #81

    Microsoft 365
    Camera_XHS_17823326846761040g008321qgi9fkno6g5o0tc3508l2pihk6l10~2|403x500

  • 青年杰出贡献上交大門人 紫金港第一皮革<・)))><< Post #161

    明天开始期末考 有点害怕

  • IO IO Post #1

    https://xjtu.men/

    ⚠️ Expect bugs. Please help developer catch them.

    Support static username+password / GitHub / xjtu.app / Discourse ID SSO login.
    Expect bugs.

    No mysterious CloudFlare 1000 Error on xjtu.men domain.

    Why Sveltekit makes user feels fast, for one reason:

    tl;dr 鼠标悬浮到链接上时就开始从服务器预加载该页面的数据, 如果访问者进一步点击了该链接那么就无需再从服务器请求数据了.

    data-sveltekit-preload-data

    Before the browser registers that the user has clicked on a link, we can detect that they've hovered the mouse over it (on desktop) or that a touchstart or mousedown event was triggered. In both cases, we can make an educated guess that a click event is coming.

    SvelteKit can use this information to get a head start on importing the code and fetching the page's data, which can give us an extra couple of hundred milliseconds — the difference between a user interface that feels laggy and one that feels snappy.

  • 一只玉米人 玉米🌽 Post #224

    距离毕业11天(20260613)

    698737d522c2c3b73dcdb92d81c26ef1|666x500
    0a27fc1b1334ab11f01bffe0f335e4a8|666x500
    2a002feb0e821892d4ee3cb53cbf63f6|666x500
    7479780616183f56558b573bad55282c|666x500

    ​(p1-p3)
    10:00-15:30
    ​依旧备课。为了花完钱图咖啡厅里的钱,今天狂点松饼🥞冰激凌🍦➕大杯摩卡咖啡[咖啡]。另外,今天是我四年来第一次在咖啡厅里自习,以前都是打包带走。。。还是在现场吃有氛围。😚
    ​(p4)
    ​晚饭吃饺子🥟,平常我都配的辣椒油,今天配小香醋。
    因为昨天的MRI诊断结果上说疑似存在颌下腺导管结石。在网上搜的缓解方法是吃点酸的,多分泌唾液可以冲出来。🥲

  • 一只玉米人 玉米🌽 Post #222
  • 一只玉米人 玉米🌽 Post #227

    毕业倒计时8天(20260616)
    p1:昨天在主楼平台拍抽象毕业照,被路人拍到。

    微信图片_2026-06-17_142817_454|227x499
    5e72763f5f2096fa24490c0fcae62f03|666x500
    047a206576269bb9afafbdcbcc072caa|666x500
    dbdde19e0a6775f9f0b68d27a35f31c2|666x500
    acf35ca9ad8e4dc2826b1fb6b710a093|666x500

    昨天中午我在朋友圈发完豆包小视频之后,分别有两个同学告诉我,在各自的小群里看见我了。🤣
    说到我(豆包)头上的小红帽,本来我们预定的是 Make XJTU Great Again,谁知道发来了个 Make SJTU Great Again,但校徽是西交的。😇 啥时候两校能合并啊?Make JiaoTong Great Again!😡👊🏻
    后续是商家承诺再做一套帽子补发,但是不知道啥时候能到,所以我们就先用MSGA了,找找角度可以不漏出来S

    p2-p4:与同门找导师在论文提交意见书上签字,并在数学楼前合影。(就不在这里放合影了)
    p5:班主任老师带着吃东北铁锅炖,边上的烤馍真好吃!😋

    15ca8b61c030708295e2b6bc33ad1f3a|690x499
    微信图片_2026-06-17_230254_219|690x288

    p6、p7:真成xhs大V了,也是让我蹭到西交官号了。😎

  • Xrystal-line 羽流弦ノ迹 Post #4

    你不会是机院大群里的几个水王之一吧?给你盒了 😉

    我和你同级,隔壁智造的,但是寝室里其他人全是你们专业的,显得我比较离群。

    我能体会到题主的感受,天天刷知乎什么的事情我也一样,所以也写一些建议吧。

    个人建议是先忘掉挂科问题,沉没成本不参与重大决策,不能一直想着挂了科就提前自我否定了。

    然后现在就行动,尽量多尝试,找一些未来的落脚点,而不是等到考研究生孤注一掷,当然可以做好坏打算,但是当下永远是最佳时机。
    和上面门友一样,建议找老师或者类似方向的学长聊聊,包括但不限于选修课老师或者各种高平台的?然后借此做一些事。甚至实在不行的话,到机院做故障诊断组的去实习应该也很有益。故障诊断这些也很偏软件了。你交机械在这方面比较强的。

    我之前认识的一个智造学长就直接找了具身相关的方向,现在发展很不错。

    当然门友也有很多优秀学长,等回复吧。

    另外你门又有新人,也是好起来了。

  • i13l
    TwlnfuSprig TwlnfuSprig Post #260

    😗看别人写的致谢好好玩,有的是整个四年的缩影,玩梗的也有感伤的也有

    总之透过致谢去反推本来是一个多有趣的人还蛮好玩的

  • i13l
    一只玉米人 玉米🌽 Post #261

    🌽玉米人也在憋致谢中 🐁

  • i13l
    TwlnfuSprig TwlnfuSprig Post #262

    😗总算是上来了,不知道还会在門氵多久

    之前又双进货了批绿豆冰沙,不过有几杯放在冰箱里久了已经能看出分层了,摇一摇不影响口感就是了

    不是最近*雪峰的事po都没意识到自己已经快一年没吃过冰棒类的东西了,购入了一些巧乐兹,还是很好吃,就是要这种脆脆的带点实心的巧克力雪糕

    不过四个圈就很一般了,吃到最后的夹心巨容易掉包装袋里甚至掉出来,也不知道是怎么设计的.....虽然能吃到的部分肯定比巧乐兹多