把你的知识变成一颗颗可以拖拽、会自己漂动的星球。
纯前端静态知识管理页 —— HTML + CSS + 原生 JavaScript,没有后端、没有数据库、没有任何框架、没有外部 CDN。所有数据存在浏览器 localStorage 里,双击 index.html 就能跑。
直接双击 index.html。
如果浏览器对 file:// 的 localStorage 做了限制(极少数情况),用任意静态服务器打开即可:
cd StarNotes
python -m http.server 8080
# 然后访问 http://localhost:8080桌面上已经放好「星笔记 StarNotes」快捷方式,双击即用默认浏览器打开 index.html。
它是一个 .url 文件(Internet 快捷方式,纯文本),想改指向直接用记事本编辑即可;图标来自项目根目录的 favicon.ico。
favicon.ico 是 tools/make-icon.js 用纯 Node 生成的(自己编码 PNG + ICO,无依赖)。想换配色改脚本里的常量后重跑:
node tools/make-icon.js D:/StarNotes/favicon.ico| 文件 | 作用 |
|---|---|
index.html |
星球导航首页(顶层星球)+ 右上角常驻的今日任务 |
category.html |
下一级星图,用 ?id=xxx 指定进入哪颗星球 |
note.html |
笔记页,块编辑器 + 大纲侧栏 |
calendar.html |
日历页,月历 + 每日任务 |
css/style.css |
全部样式 |
js/store.js |
数据层:localStorage 读写、增删改查、日期工具、示例数据 |
js/blocks.js |
块编辑器(大标题 / 中标题 / 小标题 / 正文 / 代码) |
js/ui.js |
弹窗、确认框、右键菜单、轻提示、颜色工具 |
js/planet-view.js |
星球渲染、拖拽、漂浮 |
js/calendar.js |
月历网格与任务列表渲染(只画 DOM,不碰数据) |
js/day-panel.js |
当天任务面板(日历页右侧、首页右上角共用同一套交互) |
js/page-map.js |
星图页逻辑(首页和分类页共用;今日任务面板只有首页有) |
js/page-note.js |
笔记页逻辑(自动保存 + 大纲定位) |
js/page-calendar.js |
日历页逻辑(选日期、翻月) |
页面之间用普通跳转 + URL 参数传 id,脚本是经典 <script> 而非 ES Module —— 因为 type="module" 在 file:// 下会被 CORS 拦截,双击打开会白屏。
星图页
- 星球名字写在气泡里,气泡半透明、自带缓慢漂浮;拖拽调整位置,松手自动保存,停下后会平滑地接回漂浮轨迹
- 位置按百分比存,窗口缩放不会跑偏
- 有子星球的星球外面套一圈虚线轨道,仅此一个区分标记,没有别的角标
- 单击进入星球:有子星球 → 进下一级星图;没有子星球 → 直接进它自己的笔记
- 右键气泡 → 打开 / 编辑 / 添加子星球 / 删除(双击空白处也能快速新建)
- 键盘:
Tab聚焦气泡后,Enter进入,方向键微调位置(按住Shift步长更大) - 顶部只有一条导航栏,当前在哪颗星球看面包屑;不设大标题
- 右下角是主要动作:「编辑」改当前这颗星球的名称和颜色,「添加星球 / 添加子星球」新建;左下角一行操作提示
- 导航栏右侧「数据」可以导出 JSON 备份、导入、恢复示例数据
- 右上角常驻一栏「今天」:打开首页就能看见今天要干什么,直接勾、直接在底下输入框加,不用先进日历页;
加任务、勾选、双击改文字、删除的整套操作和日历页那块是同一个(
js/day-panel.js) - 右上角那栏可以按
›收起,收起后原地留个小胶囊写着还剩几件,点一下又展开; 收没收起会记住(存在starnotes.today.folded,和笔记数据分开放) - 星球活动的地方永远避开了这一栏:舞台本身就让出了右边一条,所以没有哪颗星球会被面板压住。 这跟面板收没收起无关 —— 否则一收一放,星球就会被边界约束挤着往左挪,位置是要写回本地的
- 页面开着过夜也不怕:切回窗口时如果跨天了,这一栏会自己翻到新的一天
笔记页
- 一篇笔记就是一串「块」,每块自己是一种类型,点顶部按钮切换当前块:
大标题/中标题/小标题/正文/代码 - 所见即所得,没有「源码 / 预览」来回切;改完 700ms 自动保存,
Ctrl/Cmd + S立即保存 - 左侧是一条贴着窗口左边缘的常驻大纲,打开页面就在,不用先写出标题; 三层标题用不同字号、粗细和缩进区分层级,点一下平滑跳过去,滚动时自动高亮当前章节; 点标题旁边的「大纲」可以收起 / 展开(收放完全由你决定,不会自动变)
- 右上角「编辑星球」可改名称和颜色
日历页
- 顶栏「日历」进入,任意页面都能进;按钮上的小红点写着今天还剩几件没做完
- 打开就落在今天,右边直接列出当天的任务,不用先去找
- 左边月历,一周从周一开始;今天描边,选中填充,有任务的日子底下画点(超过 3 条改显示条数)
- 点哪天就切到哪天;双击某天直接跳到那天的输入框
- 添加任务:输入框里回车,或者点「添加」。加完输入框留着焦点,可以连着录好几条
- 勾选后任务会沉到列表底部,取消勾选再浮上来;「清除已完成」一次清掉当天的
- 改文字:双击任务文字就地改,
Enter保存 /Esc放弃 / 点别处也算保存。清空会被挡住,原文留着 - 删任务:鼠标移上去点
×,或者在任务上右键 - 翻月时选中的日期会跟着落进新月份(本月有今天就选今天,否则选 1 号),不会出现「月历是 10 月、面板还写着 9/26」
- 上个月末尾、下个月开头那几天是淡色但不失效的格子,照样能点能加任务
- 选了哪天会写进地址栏(
calendar.html?date=2026-09-26),刷新还停在原地
任务就是「哪一天 + 一句话 + 勾没勾」,只属于那一天,不做重复规则,也和星球没有关系。
这一页右边那块面板和首页右上角那块是同一个组件(js/day-panel.js),
区别只有两点:这里跟着你选中的日期走、多一个「清除已完成」;首页那块日期钉死在今天。
快捷键(笔记页)
| 按键 | 作用 |
|---|---|
Enter |
新建下一块(代码块内是换行,Ctrl/Cmd + Enter 才是新建块) |
↑ / ↓ |
切换块类型,转圈循环;代码块内是移动光标 |
Shift + Enter |
块内换行 |
Backspace |
空块上按下会删掉这一块 |
Tab |
缩进两个空格 |
Ctrl/Cmd + Alt + 1/2/3/0/C |
切换块类型 |
类型梯子是 正文 → 大标题 → 中标题 → 小标题 → 正文 转圈:↑ 往大标题走,↓ 往正文走,
所以在新块上按 ↑ 是「升级成标题」,在大标题上按 ↓ 就是中标题。
任何块都能这么切,不限于空块,也不用按 Alt —— 已经有内容的正文按 ↑ 就直接变成小标题,
文字原样保留,只是换个样子。只有代码块例外:那里方向键要留给光标(不然没法写代码),
想改代码块类型只能点顶部按钮。
最顺手的写法:Enter 开一个新块 → ↑ 挑类型 → 直接打字。
快捷键(日历页)
先 Tab 把焦点放进月历,方向键才生效。
| 按键 | 作用 |
|---|---|
← / → |
前 / 后一天 |
↑ / ↓ |
前 / 后一周 |
Home / End |
本周一 / 本周日 |
PageUp / PageDown |
上 / 下个月 |
T |
回到今天 |
任务列表里:Tab 走到复选框按空格勾选,双击(触屏点一下)文字可以改,Enter 保存、Esc 放弃。
{
version: 3,
tasks: [{ // 每日任务,和星球没有关系
id: 't_xxx',
date: '2026-09-26', // 'YYYY-MM-DD',本地日期
text: '写周报',
done: false,
createdAt, updatedAt
}],
planets: [{
id: 'p_xxx',
name: '八股',
color: '#EE6E90',
parentId: null, // null 表示顶层星球
x: 0.5, y: 0.4, // 画布中的相对位置,0~1
blocks: [ // 笔记内容
{ id: 'b_xxx', type: 'h1'|'h2'|'h3'|'text'|'code', text: '' }
],
createdAt, updatedAt
}]
}存于 localStorage['starnotes.data.v1'](键名里的 v1 是历史遗留,不要再动它,改了等于把所有人的数据清空)。首次打开会写入一份示例数据(项目 / AI Coding / 算法 / 八股 / 源码阅读)。
日期用 'YYYY-MM-DD' 字符串存,不用时间戳:它字典序可比,按月筛任务不用真的解析日期。算这个字符串只看本地年月日,绝不走 toISOString()(那个按 UTC 输出,东八区晚上会整体少一天),也不写 new Date('2026-09-26')(那串按 UTC 午夜解析,换个时区就差一天)。
任务在列表里的顺序:未完成在前、已完成沉底,各自内部按 createdAt 升序。
星球不区分「分类 / 笔记」,只看有没有子星球:有子星球就是分类,没有就是一篇笔记。给一篇写好的笔记添加子星球,它会变成分类,原来的内容仍然保留在对象里。
旧版本(v1,Markdown 正文 + emoji 图标)的数据打开时会自动迁移:#/##/### 变成对应级别的标题块,围栏代码块变成代码块,其余按正文处理。
v2 → v3 是纯增量:老的备份没有 tasks 字段,导入时自动补成空数组,不会报错。反过来说,别拿 v3 导出的备份去喂旧版本 —— 旧版的清洗逻辑不认识 tasks,会把任务整个丢掉。
删除星球会级联删除其下所有子星球,导入数据时会自动清理父节点不存在的孤儿节点,损坏的字段会被纠正为合法值。
- 数据只在当前浏览器里,换设备请用「数据 → 导出数据」走 JSON
- 任务没有重复规则,不做「每天 / 每周」自动重现;也没有提醒和通知,纯靠你自己打开看
- 任务和星球互不相干,不能把任务挂到某颗星球上
- 同一个浏览器开两个标签页会互相覆盖:两边各持一份内存里的数据,谁后保存谁赢。这个坑星球时代就有,只是任务天天写会更明显
- 笔记内容存在单个星球对象里,单篇特别长(几万字)时 localStorage 会比较吃紧
- 拖拽位置按百分比存,同一颗星球在不同窗口尺寸下位置比例一致,但不会自动避让重叠 —— 重叠了手动拖开就行
- 首页右上角那栏今日任务是常驻的,代价是星图右边固定少掉约 356px;把浏览器窗口拉窄到 900px 以下它会自动改成浮在下方(默认收起), 再窄就点右上角的小胶囊展开。窄屏上面板展开时会盖住右下角的「添加星球」,所以那几个按钮会先让位
- 收起面板不会把星图右边那块地方还回来。这是故意的:收放一旦改变星球的活动范围,被挤到边上的星球就会把新位置写回本地,来回几次就漂走了
- 漂浮位移是每帧算的,不写进 localStorage,刷新后回到你摆放的位置