☰
我用一个 bookmarklet 做了个“老板键”:任意网页一键切换成“认真工作”界面(附在线体验+源码)
2026/10/3 20:04:22 网站建设 项目流程

上班摸鱼最怕什么?老板突然出现在身后。 于是我用一段bookmarklet(书签小工具)实现了一个"老板键":在任何网页上点一下,屏幕瞬间全屏变成代码编辑器 / 数据表格 / 在线会议 / 工作文档;老板走后再点一下(或按Esc),一切原样回来。 不需要安装浏览器扩展、不需要后端、纯原生 HTML/CSS/JS,单文件即可运行。

在线体验地址(点开即用,建议用电脑浏览器):https://dochost.co/d/v7ki5ghd

开源仓库(MIT,欢迎 Star / Fork):https://dochost.co/d/v7ki5ghd

下面把核心实现拆开讲清楚,文末附完整源码地址。


一、先看效果

  • 平时它是一个"摸鱼看板":有下班倒计时,还会实时计算"今天打工已经赚到多少钱""每秒进账多少"。
  • 按下触发键(默认反引号`,也可以点页面上的按钮),整个屏幕立刻被一个全屏遮罩盖住,变成一个以假乱真的代码编辑器:左侧有资源管理器、顶部有标签页、代码带语法高亮、还有闪烁的光标。
  • 伪装状态下按1 / 2 / 3 / 4,可以在代码、表格、会议、文档四种界面之间快速切换;按Esc或再点一次书签即可恢复。
  • 连浏览器标签页的标题都会一起伪装(比如变成"季度工作进展汇报 - 文档"),防止从标签栏露馅。

四种伪装界面全部是原创的通用样式,没有使用任何真实软件的商标或界面,也不含任何真实数据。


二、为什么用 bookmarklet,而不是浏览器扩展?

常见的"老板键"一般做成浏览器扩展,但扩展有几个麻烦:

  1. 要打包、要上架审核(Chrome、Edge 各自一套),安装也麻烦;
  2. 扩展权限大,用户天然警惕;
  3. 换台电脑、换个浏览器就不能用。

而bookmarklet(书签小工具)本质上就是一个网址以javascript:开头的书签。把它拖到书签栏后,在任何网页点一下,浏览器就会在当前页面执行这段 JS。它:

  • 无需安装、无需审核、跨浏览器通用;
  • 只在你主动点击时运行,不常驻、不后台联网;
  • 代码完全透明,右键"编辑书签"就能看到全部逻辑。

关键问题是:怎么把一大段功能"塞进"一个书签里?答案是Function.prototype.toString()。


三、核心实现拆解

3.1 写一个自包含的伪装函数

我把所有伪装逻辑封装进一个函数BOSS_KEY(cfg)。它做的事:

  1. 动态创建一个<style>,注入伪装界面所需的全部 CSS;
  2. 创建一个全屏position:fixed; inset:0; z-index:2147483647的遮罩层;
  3. 根据配置渲染对应界面(代码 / 表格 / 会议 / 文档);
  4. 监听keydown:按Esc关闭、按1~4切换界面;
  5. 同时伪装document.title。

函数骨架大致是这样(有删减):

function BOSS_KEY(cfg){ cfg = Object.assign({ disguise:'code', title:'季度工作进展汇报 - 文档', loop:true }, cfg||{}); var ID='__boss_key_overlay__'; var oldTitle=document.title, current=cfg.disguise, timers=[]; function shutdown(){ // 解除伪装 var o=document.getElementById(ID); if(o)o.remove(); var s=document.getElementById(ID+'-style'); if(s)s.remove(); document.removeEventListener('keydown', onKey, true); timers.forEach(clearInterval); timers=[]; document.title=oldTitle; } if(document.getElementById(ID)){ // 防止重复注入:已存在则直接关闭 if(typeof window.__boss_key_shutdown==='function') window.__boss_key_shutdown(); return; } window.__boss_key_shutdown=shutdown; // ... 注入 CSS、创建遮罩、根据 current 渲染对应视图 ... function onKey(e){ if(e.key==='Escape'){ shutdown(); return; } if(cfg.loop && ['1','2','3','4'].indexOf(e.key)>=0){ timers.forEach(clearInterval); timers=[]; current=order[parseInt(e.key,10)-1]; render(); } } document.addEventListener('keydown', onKey, true); render(); document.title=cfg.title; }

几个值得注意的细节:

  • 用固定的 DOM id(__boss_key_overlay__)做幂等:如果遮罩已经存在,再次触发就直接关闭,而不是叠两层。
  • 关闭时要彻底清理:移除遮罩和样式、移除事件监听、清掉所有定时器、还原标题,避免在别人的网页里留下垃圾。
  • 事件监听用捕获阶段(第三个参数true),保证按键能被优先拿到。

3.2 关键技巧:把函数"序列化"进 javascript: URL

书签里没法直接写一大段函数,但我们可以在"安装页"里利用toString()拿到函数的完整源码字符串,再拼进javascript:URL:

function makeBookmarklet(cfg){ var src = '(' + BOSS_KEY.toString() + ')(' + JSON.stringify(cfg) + ');'; return { url: 'javascript:' + encodeURIComponent(src), len: src.length }; }

这里发生了三件事:

  1. BOSS_KEY.toString()返回这个函数的完整源代码文本;
  2. 用(函数源码)(配置)的形式包成立即执行表达式,配置通过JSON.stringify内联进去;
  3. 最后encodeURIComponent编码,前面加上javascript:前缀,就得到了书签的网址。

页面上那个绿色的"拖我到书签栏"按钮,它的href就是这样生成的:

var bm = makeBookmarklet(readCfg()); bmLink.href = bm.url;

用户把按钮拖到书签栏,等于把这段javascript:网址存成了书签;以后在任何页面点它,浏览器就会执行BOSS_KEY(配置)。

小提示:javascript:书签在页面上下文里运行,所以它能操作当前页的 DOM、注入全屏遮罩;这也是它比"单独开一个伪装网页"更强的地方——它是在你正在摸鱼的那个页面原地伪装,不会留下多余标签页。

3.3 伪装视图:用字符串模板拼出"以假乱真"的界面

四种界面本质上都是返回一段 HTML 字符串,再塞进遮罩。以"代码编辑器"为例,我准备了一组带语法高亮 class 的代码行,渲染时加上行号、侧边栏、标签页和一个闪烁光标:

var codeLines = [ "<span class='tok-c'>// 季度数据汇总工具</span>", "<span class='tok-k'>function</span> <span class='tok-f'>buildQuarterReport</span>(rows) {", " <span class='tok-k'>const</span> total = rows.<span class='tok-f'>reduce</span>((s,r)=>s+r.value, <span class='tok-n'>0</span>);", // ... ]; function viewCode(){ var lns = codeLines.map(function(l,i){ return "<div class='ln'><span class='no'>"+(i+1)+"</span><span class='code-line'>"+l+"</span></div>"; }).join(''); return "<div class='code'> ... "+lns+" ... </div>"; }

光标闪烁纯靠 CSS 动画:

.cursor{display:inline-block;width:8px;height:16px;background:#9cd0ff;vertical-align:-3px;animation:bkblink 1s steps(1) infinite} @keyframes bkblink{50%{opacity:0}}

"在线会议"界面还会每隔 1.8 秒随机高亮一位"正在发言"的同事,并实时更新会议时长,让画面是"活"的:

meetTimer=setInterval(function(){ tiles.forEach(function(t){ t.classList.remove('speak'); }); tiles[Math.floor(Math.random()*tiles.length)].classList.add('speak'); },1800);

3.4 彩蛋:实时"今日已赚 / 每秒进账"

摸鱼看板上最有"情绪价值"的一块,是看着自己摸鱼的每一秒还在"进账"。计算逻辑很简单:

var JOB_DEF={salary:8000, workDays:21.75, start:'09:00', end:'18:00'}; function tickEarn(){ var s=t2m(jobCfg.start), e=t2m(jobCfg.end), work=e-s; var daySalary=jobCfg.salary/(jobCfg.workDays||21.75); // 日薪 = 月薪 / 计薪天数 var rate=work>0 ? daySalary/(work*60) : 0; // 每秒进账 var mins=now.getHours()*60+now.getMinutes()+now.getSeconds()/60; var worked=Math.max(0,Math.min(work,mins-s)); // 今天已工作分钟数 var earned=worked*60*rate; // 今日已赚 // ...更新页面;周末则显示"周末休息" } setInterval(tickEarn,1000);

月薪、计薪天数、上下班时间都可以在页面上自定义,存在localStorage里,下次打开还在。

以月薪 8000、每月计薪 21.75 天、朝九晚六为例:日薪约 367.8 元,每秒进账约 0.011 元——摸鱼五分钟,大概"赚"了三块多,属于打工人的一点精神胜利。


四、在线体验 & 完整源码

  • 在线体验(点开即用):https://dochost.co/d/v7ki5ghd
  • GitHub 源码(MIT License):https://dochost.co/d/v7ki5ghd

打开页面后:

  1. 可以直接点"立即体验"按钮看伪装效果,按Esc返回;
  2. 把绿色按钮拖到书签栏,就能在任何网页一键使用;
  3. 在设置里改成自己的月薪、上下班时间和喜欢的伪装界面,点"生成我的老板键"即可。

五、写在最后

这个小工具用到的知识点其实很朴素:Function.prototype.toString()序列化、动态注入 CSS/DOM、全屏遮罩、键盘事件、localStorage持久化——但组合起来确实能解决一个"痛点",也算是 bookmarklet 这种"古老"技术的一个有趣应用。

几点说明:

  • 项目基于 MIT 协议开源,仅供娱乐与学习,请合理安排工作、注意休息;
  • 所有伪装界面均为原创通用样式,不含任何真实公司、软件商标或个人数据;
  • 书签只在本地运行、不联网、不上传任何数据。

如果觉得有意思,欢迎到 GitHub 给个 Star,也欢迎在评论区交流 bookmarklet 的其他玩法~

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询