# memory-sea-mirror **Repository Path**: N_code/memory-sea-mirror ## Basic Information - **Project Name**: memory-sea-mirror - **Description**: 记忆海-镜子 把日常想法裂变成3D星云的认知日记本. - **Primary Language**: JavaScript - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: https://jiyihai.cc.cd/ - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-06 - **Last Updated**: 2026-11-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 记忆海-镜子 · 模板 **中文 |** **[English](README_en.md)** # 🌌 小白半小时零代码四步部署:「记忆海-镜子」打造你的专属 3D 日记网站教程地址: http://luren.bot.cd/posts/jiyihai.html **在线演示:**(演示站只读内存数据,不写入本机或服务器) > 这不是一个效率工具,这是一面照见意识结构的镜子。 ## 效果图 ![星图效果](https://i.imgs.ovh/2026/11/07/9bb118b4fdbe82fd0ea60645cc5d0aee.jpg) ![小银河效果](https://i.imgs.ovh/2026/11/07/4d5ca04dff748d9409d195cac4bf80a0.jpg) ## 关于 ### 为什么做这个? 起初,只是因为熬了一个难熬的夜班。一天过去,做了很多事,想了很多念头,最后却觉得什么都没留下,仿佛被巨大的虚无感吞噬。 我们试过传统的日记、双链笔记、标签管理器,但最后发现,我们只是在做「知识收纳」,而不是在「梳理内心」。于是,有了这片星云。 ### 它是什么? - **不是相册,是镜子**:它把你内在不可见的联想网络,外化为可以旋转、可以点亮的星空。 - **极简输入,极繁输出**:你只需倾倒情绪,AI 会在后台将其裂变为实体节点与因果连线。 - **照见你的微观宇宙**:中心的观测点(显意识),旋转的星团(日常与情绪),以及暗处未被点亮的孤星(潜意识)。 > **一句忠告** > > 不要为了照镜子而照镜子,更不要为了把玩镜子而照镜子。 > > 镜子是用来照的,不是用来盘的。 > > 工具只是梯子,用完就要撤。如果你今天觉得很累,或者为了怎么调节点颜色而纠结了半小时,请立刻关掉这个网页,去真实地吃一顿饭,去感受风吹过皮肤,去好好睡一觉。 > > **生活本身,才是主产品。** > “只要你还能因为一个绝妙的想法而感到战栗,你的宇宙就依然在运转。” 把「记忆海-镜子」变成你自己的版本:一个单文件页面 + 零依赖 Node 服务,用来把想法、人物、事件、知识做成可旋转、可点击的 3D 星云图。 当前为**空白模板**:启动后只有「观测点」和 8 个分层(日记、日常活动、身体状态、情绪暗流、人际互动、认知沉淀、未来锚点、梦境),其中「梦境」默认带一个「梦」节点,内容由你自己录、导入或在日记抽屉里写。 ## 项目架构 整体是「单文件前端 + 零依赖 Node 服务 + 文件存储」,没有数据库、没有构建步骤: ```text 浏览器(index.html) ├─ 配置层 TEMPLATE:标题、分层、演示数据、突触修剪参数、本地存储键 ├─ 渲染层 Canvas 2D 手写 3D 投影;8 种视图与出生/旋转/斥力动效 ├─ 交互层 选中、检索、分层过滤、新增节点/分层、手动关联、视角控制 ├─ 数据层 nodes / edges / layers 常驻内存;localStorage 缓存 + PUT /api/graph 同步 └─ 日记抽屉 文本 → POST /api/ai-parse → 返回实体与关系 → 写入图谱 Node 服务(server.js) ├─ 静态服务 下发 index.html;拦截 data/ 与隐藏文件 ├─ 访问门禁 登录页 + Cookie 会话(12 小时免登,无操作自动退出) ├─ REST API GET/PUT/DELETE /api/graph、POST /api/ai-parse、 │ POST /api/save-diary-txt、GET /health ├─ 文件存储 data/graph.json、*.bak(上一版)、diary_log.md(日记原文) └─ 模型代理 服务端调用 DeepSeek,LLM_API_KEY 不下发到前端 部署链路:本地 docker build → 推送阿里云 ACR → Sealos 拉镜像运行 (单实例 + PVC 挂载 /app/data) ``` 数据流:页面改动先写入浏览器本地缓存,再 `PUT /api/graph` 覆盖服务器快照;服务端保存前把旧文件复制为 `.bak`。日记抽屉额外把原文追加到 `data/diary_log.md`。 ## 功能 - **3D 星云图谱**:8 种视图(星云、小银河、聚类、列表、矩阵、旭日、思维导图、阅读),支持旋转、缩放、平移、选中居中。 - **分层管理**:8 个默认分层(含梦境),可新增自定义分层、单独显示/隐藏、按标题/描述检索过滤。 - **节点编辑**:新增节点、手动建立关联、编辑描述与权重;分层与节点都随快照保存。 - **AI 日记裂变**:一篇日记自动拆成 2–4 个实体,按语义落到对应分层,并用「包含 / 导致 / 引发」等关系连回日记主节点。 - **突触修剪**:长期未打开的节点逐渐变暗、到期限后隐藏,点开即恢复,模拟记忆遗忘。 - **数据导入导出**:JSON 快照导入/导出,Markdown 导出;服务端支持 `PUT` 直接写入整份图谱。 - **私密与门禁**:登录页 + Cookie 会话(12 小时免登)、无操作自动退出、`data/` 与隐藏文件不可通过 URL 下载。 - **持久化部署**:Sealos + PVC,重启/重新部署不丢数据;单实例写入,避免多副本冲突。 ## 快速开始 ```bash npm start # 等同 node server.js # 打开 http://localhost:8787 ``` 自定义端口: ```bash # Windows PowerShell $env:PORT=9000; node server.js # macOS / Linux PORT=9000 node server.js ``` 启用 AI 日记裂变(Node >= 18): 1. 打开项目根目录的 `.env`,填写 `LLM_API_KEY=你的Key`(可同时改 `LLM_API_URL`、`LLM_MODEL`)。 2. 重启服务:`npm start`。 `.env` 只被服务端读取,已加入 `.gitignore`,不会提交到 Git,也不会出现在前端。 也可以临时用环境变量覆盖(环境变量优先): ```bash # Windows PowerShell $env:LLM_API_KEY='你的 Key'; npm start # macOS / Linux LLM_API_KEY=你的Key npm start ``` 可选配置:`LLM_API_URL`(默认 DeepSeek `https://api.deepseek.com/chat/completions`)、`LLM_MODEL`(默认 `deepseek-chat`)、`LLM_TIMEOUT_MS`(默认 60000)。 ## 隐私与访问门禁 站点包含私密日记,部署到公网前必须先设置访问密码: ```bash # .env 或部署平台环境变量 SITE_USER=你的用户名 # 可选,默认 admin SITE_PASS=你的强密码 # 必填;不设置则门禁关闭(启动时打印警告) ``` - 设置 `SITE_PASS` 后,未登录访问 `/` 会收到内置登录页(`POST /api/login` 校验账号密码),成功后在浏览器种下 `msm_sess` 会话 Cookie(HttpOnly,12 小时有效),期间刷新无需重复登录;不再使用浏览器 Basic Auth 弹窗。 - 未设置 `SITE_PASS` 时服务照常启动,但访问门禁关闭,仅适合本机调试。 - `data/` 目录下的任何文件(`graph.json`、`diary_log.md` 等)都不能通过 URL 直接下载,静态服务会拒绝;数据只通过 `GET /api/graph` 在内存中读取返回。 - 隐藏文件(如 `.env`)也不会被静态服务下发。 - 登录失败限流:同一 IP 15 分钟内密码错误 5 次即锁定 15 分钟,锁定期间即使密码正确也返回 `429`,防止无限爆破;同一组错误密码重复请求只计一次,避免浏览器重试导致误锁。 - 前端 12 小时无鼠标/键盘操作后自动退出:调用 `POST /api/logout` 清掉会话 Cookie 并刷新,回到登录页。 - 优雅登出:右上角「登出」按钮弹出全屏毛玻璃遮罩(「🌌 镜子已闭合,星光已暂时隐去」+「🚀 重新连接」);点「重新连接」会 POST `/api/logout` 销毁服务端会话并清 Cookie,刷新后回到登录页。 - 公网 HTTPS 由部署平台(如 Sealos)自动提供,代码侧无需处理。 ## 改成你自己的站点 所有可配置项集中在 `index.html` 顶部的 `TEMPLATE` 对象(约第 441 行): | 字段 | 说明 | | --------------------------------------- | --------------------------------------------------------------------- | | `title` / `subtitle` / `version` | 页面标题、页头名称、版本号 | | `hubTitle` / `hubDesc` | 中心节点(观测点)的名称与说明 | | `layers` | 分层列表:`id`(内部标识,保存过数据后不要改)、`label`(显示名)、`color`(颜色)、`desc`(选中该层时显示的介绍) | | `demo` | `true` 生成少量示例节点;`false` 启动为空分层(模板默认) | | `forgetStartDays` / `forgetHideDays` | 突触修剪:多少天未打开开始变暗、多少天后完全隐藏(默认 30 / 90) | | `source` | 页头「来源 xxx」,留空则不显示 | | `exportName` | 导出 Markdown / JSON 的文件名前缀 | | `storageKey` / `presetKey` / `tokenKey` | 浏览器本地存储键;同一域名部署多份时必须改成不同前缀 | ### 新增内容 页面上可以直接操作: 1. **新增节点**:点「+ 新增节点」,填标题、分层、描述、权重即可。 2. **新增分层**:点「+ 新增分层」,输入名称后建立一个自定义分层;分层会写入快照,保存过数据后 `id` 不要随意更改。 也可以改代码:在 `index.html` 的 `if (TEMPLATE.demo) { ... }` 分支里按下面的结构加: ```js layer('knowledge', [ // [标题, 描述, 权重(0.3–1), 附加字段(可选)] ['复利', '收益随时间的自我强化。', 0.8], ['沉没成本', '已经付出、无法收回的成本。', 0.6, { flag: '待补' }] ]); ``` ### 导入现成资料 左侧「数据」区可以导入 JSON(按快照恢复节点、连线与分层信息),也可以导出 JSON / Markdown;暂不支持导入 Word 或 Markdown。服务端可以用 `/api/graph` 直接 PUT 一份 JSON(见下文)。 导入是**全量覆盖**而非合并:选中文件后会弹出二次确认(显示当前与文件中的光点/连线数量),确认后服务端先把现有图谱归档到 `data/backups/`,再写入新图谱;取消则图谱不做任何改动。导入前不做下载备份。 手动连线:选中一个节点 → 「+ 关联节点」→ 点另一个节点,可建立 `relates` 关系,用虚线显示。 ## 日记裂变(AI) 点击页面右下角的 📝,写下日记后点「发射进入星云」。前端会把文本发给 `POST /api/ai-parse`,由服务端调用大模型拆成 2–4 个实体和关系: 1. 新建一个「日记」层主节点(`diary_时间戳`),保存日记全文。 2. 同名实体自动复用;新实体按 AI 判断落到「日常活动 / 身体状态 / 情绪暗流 / 人际互动 / 认知沉淀 / 未来锚点」之一。 3. 日记主节点用「包含」连线指向各实体,实体之间使用 AI 识别的关系词(如「导致」「引发」)。 4. 新节点从主节点位置出生,1 秒内放大,并借助力导向斥力向外散开。 5. 结果立即保存到本机和服务器。 未配置 `LLM_API_KEY` 时接口会返回明确错误,页面会提示,不会静默失败。 ## 分层 | 分层 | 适合放什么 | | ---- | ------------ | | 日记 | 日记主节点 | | 日常活动 | 洗衣服、通勤、做饭、工作 | | 身体状态 | 失眠、疲惫、胃疼、运动 | | 情绪暗流 | 焦虑、开心、内耗、平静 | | 人际互动 | 家人、同事、朋友 | | 认知沉淀 | 知识、灵感、感悟、书籍 | | 未来锚点 | 目标、计划、期待 | 观测点仍是中心节点,不参与分层过滤。 ### 旧数据兼容 如果你之前保存过旧分层的图(`core`、`events`、`note` 等),旧节点不会出现在新分层里,左侧过滤也会异常。测试新结构前请先备份并清空 `data/graph.json`,或先备份再用页面上的清空功能重新开始: ```powershell Copy-Item data\graph.json data\graph.old-layers.json Remove-Item data\graph.json ``` 浏览器本地也有缓存,必要时在页面里清空本地数据后再刷新。 ## 视图 星云、小银河、聚类、列表、矩阵、旭日、思维导图、阅读,共 8 种。默认「星云」为力导向布局;「小银河」是层级轨道视图。 ## 交互 | 操作 | 效果 | | -------------------- | ---------------------------------------------------------------- | | 左键拖动 | 旋转视角 | | 滚轮 | 以光标为中心缩放 | | 中键 / 右键 / Shift+左键拖动 | 平移 | | 点击节点 | 选中、居中、右侧显示详情 | | 点击左侧分层文字 | 选中该层并居中 | | 左侧分层小方框 | 显示 / 隐藏该层 | | 左侧检索框 | 按标题 / 描述搜索,点结果选中并居中 | | 「显示」区 | 调整节点大小、自动旋转、名称标签、全部文字、跨层关联、突触修剪、视角重置 | | 「漫游」 | 开启 / 停止无意识漫游:镜头缓慢漂移,每隔几秒点亮一个久未连接、偏远的节点,并像点击它一样平滑移到画面中央,同时显示节点提示框 | | 「关于」 | 打开「关于」浮层,介绍项目缘由、定位与忠告;点 ×、遮罩或按 Esc 关闭 | | 「演示 Demo」 | 仅在本机(localhost / 直接打开文件)显示,载入 1000+ 条内存演示数据,不写入服务器与本地缓存 | | Esc / 点空白 | 取消选中 | ## 突触修剪(遗忘) 节点会记录最后一次被点开的时间(`la`)。超过 `forgetStartDays`(默认 30 天)未打开后,节点逐渐变暗、连线变细;到 `forgetHideDays`(默认 90 天)完全隐藏。观测点和分层不参与修剪。 隐藏后仍可通过检索、列表、阅读视图找到,点开一次即恢复亮度并重置计时。左侧「显示 → 突触修剪」可整体关闭该机制。 ## 数据与接口 - 服务端数据:`data/graph.json`;`data/` 已在 `.gitignore` 中,不会被提交到 Git - 每次保存前把上一版复制到 `*.bak`(只保留最近一份);带 `?backup=1` 的写入(页面导入全量覆盖时使用)会额外把旧图谱归档到 `data/backups/`,文件名带时间戳 - `GET /api/graph` 读取;`PUT` 保存;`DELETE` 清空(仅 API,页面不再提供入口) - `PUT` 要求 `nodes` / `edges` 为数组、必须包含 `hub` 节点、节点不超过 5000,连线不能自环或指向不存在的节点 - `POST /api/ai-parse` 接收 `{ text }`,返回 `{ nodes, links }`;需要 `LLM_API_KEY` - `POST /api/save-diary-txt` 接收 `{ date, content, tags }`,把日记原文追加写入 `data/diary_log.md`(纯文本备份,不覆盖) - 写入令牌:设置环境变量 `WRITE_TOKEN` 后,写操作(`PUT`/`DELETE /api/graph`、`POST /api/save-diary-txt`)需带 `x-write-token` 头;页面可用 `?token=xxx` 一次写入浏览器 - `GET /health` 健康检查 - 访问门禁:设置 `SITE_PASS` 后,以上所有接口(含 `/health`)未登录时返回 `401` JSON;页面则下发登录页,`POST /api/login` 登录、`POST /api/logout` 登出 - 单实例部署:不要多副本同时写同一个数据目录 ## 部署 部署走「本地 Docker 构建 → 推送阿里云 ACR → Sealos 拉镜像运行」。完整步骤(镜像构建与推送、Sealos 应用与环境变量、PVC 挂载、上线验证、版本更新、数据备份、本地 docker 运行)见 [DEPLOY.md](DEPLOY.md)。 当前示例环境为容器端口 `8787`、数据目录 `/app/data`(必须挂持久卷),域名与镜像地址请换成你自己的。具体地址属于个人部署配置,不写进仓库。 ## 最小实现说明 - 页面是单文件 `index.html`,无构建、无框架、无 CDN 依赖。 - 服务端零依赖,只用 Node 内置模块。 - 所有 3D 投影与动画都是 Canvas 2D 手写,方便改配色和动效。 ## 更新记录 ### v2.4.0 · 2026-11-07(镜像 tag `2.4`) - 访问门禁改为站内登录页 + Cookie 会话,彻底移除浏览器 Basic Auth 弹窗;登出后点「重新连接」不再无限弹框。会话 12 小时有效,服务端内存存储。 - 登出改为「优雅登出」:右上角「登出」→ 全屏毛玻璃遮罩(「🌌 镜子已闭合,星光已暂时隐去」+「🚀 重新连接」),重连时调 `/api/logout` 清缓存并刷新。 - 导入 JSON 明确为全量覆盖:导入前弹二次确认(对比双方光点/连线数量),确认后服务端先归档到 `data/backups/`,再写入新图谱;取消则不改动。导入不再强制下载备份。 - 列表视图的日记按日期嵌套:日期节点作为分组标题,当天日记卡片列在下面并显示条数,未匹配到日期的日记归入「未归入日期」。 - 页脚改为「记忆海-镜子© 2026 By 路人」,站点名本身是开源仓库链接(悬停淡蓝发光)。 - 新增 favicon:logo.ico 以内联 base64 写入页面,单文件部署也能显示图标。 - 登录失败限流优化:同一组错误凭证重复请求只计一次失败,避免浏览器重试把正常用户锁死。 ### v2.3.0 · 2026-11-06(镜像 tag `2.3`) - 新增登录失败限流:同一 IP 15 分钟内密码错误 5 次即锁定 15 分钟,锁定期间返回 `429`(带 `Retry-After`),防止无限爆破;登录成功后计数清零。 - 左侧底部新增页脚:`© 2026 By 路人` 与站点运行时长(按天/时/分/秒实时刷新,起点为 v1.0.0 上线时间)。 - 移动端显示修复:`viewport-fit=cover` + 底部安全区内边距,页头在窄屏改为可横向滚动,避免按钮被裁切。 - 详情面板中 AI 提取实体的旧文案「由日记自动提取的实体。」按分层替换为氛围文案(如 `🫀 生理回响`、`💭 情绪共鸣`、`🌙 潜意识残影`),用户手写描述不受影响。 - 打开页面时的布局预热:先静默跑完物理收敛再绘制首帧,消除线条飞散。 - 小银河视图中心观测点固定不再随视角漂移;漫游切换间隔延长到 9–13 秒、镜头移动更缓。 - 演示数据改为「星尘 + 主星」分级亮度与大小,规模收敛到 129 个内容节点 / 138 光点 / 381 连线。 - 文档:部署章节拆到 [DEPLOY.md](DEPLOY.md),README 只保留摘要与入口。 ### v2.2.0 · 2026-11-04(镜像 tag `2.2`) - 修复新版日记按天折叠时日期不显示:详情面板归组改为沿 `belongs` 连线反查 `📅` 日期节点,标题里不带日期的新格式日记也能正确分天;旧格式(标题自带日期)仍走原逻辑兜底。 ### v2.1.0 · 2026-11-04(镜像 tag `2.1`) - 新增「关于」页面:顶部「关于」按钮打开浮层,包含项目缘由、定位、忠告与版本署名;支持 ×、遮罩、Esc 关闭。 - 本机「演示 Demo」数据扩充到 1000+ 节点:7 层实体 + 60 天 240 篇日记,并自动生成跨层关联;演示数据只存在内存,不写入服务器或本地缓存。 - 大图布局改为三维星团:节点较多的分层按斐波那契球面均匀铺开,不再全部挤在平面圆环上;节点超过 400 时关闭两两斥力,避免整张图被斥力推出屏幕。 - 无意识漫游升级:点亮节点会缓慢平移到画面中央,并自动显示节点提示框。 - 页头与 `TEMPLATE.version` 更新为 `v2.1.0`。 ### v1.5.0 · 2026-11-03(镜像 tag `1.5`) - 去掉「精简版 / 全量版」概念,改为单版本运行:移除顶部切换按钮及相关交互文案。 - 导出 Markdown 的标题和文件名不再带「精简版 / 全量版」标签,文件名统一为 `前缀-YYYY-MM-DD.md`。 - 文档:移除双版本相关说明,接口简化为 `GET /api/graph`,当前镜像 tag 更新为 `1.5`。 ### v1.4.0 · 2026-11-03(镜像 tag `1.4`) - 导出 JSON 的文件名增加日期,格式为 `前缀-graph-YYYY-MM-DD.json`;Markdown 导出原本已带日期。 - 移除页面的「恢复原文」按钮及其点击逻辑,同时删除不再使用的本地存储清理函数;接口 `DELETE /api/graph` 仍保留。 - 文档:同步移除「恢复原文」说明,当前镜像 tag 更新为 `1.4`。 ### v1.3.0 · 2026-11-03(镜像 tag `1.3`) - 修复 AI 日记拆分时人物没有进入「人际互动」:提示词明确 6 个分层含义,并要求日记中出现具体人物、对话、交流、关系时,至少一个实体归入 `people`。 - 增加中文分层名到英文 id 的映射,避免模型返回中文分层名时被兜底成「日常活动」。 - 已验证含人物名和对话的测试日记会生成人际互动节点;已写入的历史日记不会自动改层。 ### v1.2.0 · 2026-11-03(镜像 tag `1.2`) - 修复已有存档加载时的崩溃:`migrateDreamLayer()` 引用了未定义的 `DREAM_ITEMS` / `DREAM_COMPOSED`,导致顶部统计和左侧分层计数停留在初始值、状态误显示「未连接服务器」。 - 新增 7 个生活分层的介绍文案(`TEMPLATE.layers.desc`);旧存档的占位描述会在加载时自动替换,用户手动改过的描述不受影响。 - 文档:补充项目架构、功能清单和本更新记录;部署章节的当前镜像 tag 更新为 `1.2`。 ### v1.1.0 · 2026-11-03(镜像 tag `1.1`) - 修复加载服务器数据或本地快照时计数为 0、状态显示「未连接服务器」的问题。 ### v1.0.0 · 初始版本(镜像 tag `1.0`) - 单文件 3D 星云页面 + 零依赖 Node 服务。 - 8 种视图、7 个生活分层、AI 日记裂变、突触修剪、导入导出。 - Basic Auth 访问门禁、数据持久化与 Sealos + ACR 部署方案。