[{"data":1,"prerenderedAt":1095},["ShallowReactive",2],{"projects-all":3},[4,139,318,447,540,641,742,830,992],{"id":5,"title":6,"accent":7,"body":8,"category":78,"categoryLabel":79,"cover":80,"description":72,"extension":81,"featured":82,"features":83,"gallery":102,"links":103,"meta":105,"metrics":106,"navigation":82,"order":116,"path":117,"platforms":118,"related":120,"role":123,"seo":124,"slug":125,"stack":126,"status":131,"statusLabel":132,"stem":133,"summary":134,"tagline":135,"titleEn":136,"year":137,"__hash__":138},"projects\u002Fprojects\u002Fdianmo.md","点墨","orange",{"type":9,"value":10,"toc":71},"minimark",[11,15,19,26,29,53,56],[12,13,14],"h2",{"id":14},"一个学习项目",[16,17,18],"p",{},"点墨最初叫 MemTool，是一个原生内存扫描 CLI 加简易悬浮窗。后来重做成完整的悬浮窗工具：大尺寸面板、自绘数字键盘、模糊搜索、指针链、地址簿与变速，并把视觉改成和纸风格。",[16,20,21,25],{},[22,23,24],"strong",{},"使用边界","：仅用于本人拥有的离线单机游戏；不用于联机游戏、内购绕过或任何商业作弊场景。官网保留这段说明，是为了避免被误用。",[12,27,28],{"id":28},"架构",[16,30,31,32,36,37,40,41,44,45,48,49,52],{},"App 进程本身没有 root。所有内存访问都由 ",[33,34,35],"code",{},"su"," 拉起的独立 ",[33,38,39],{},"memtool-scanner"," 子进程完成：App 只负责参数、结果展示与安装。扫描器优先用 ",[33,42,43],{},"process_vm_readv\u002Fwritev","，失败回退 ",[33,46,47],{},"\u002Fproc\u002F\u003Cpid>\u002Fmem","；",[33,50,51],{},"maps"," 解析只保留可读写的匿名段。",[12,54,55],{"id":55},"视觉",[16,57,58,59,62,63,66,67,70],{},"界面用 ",[33,60,61],{},"#EFE7D6"," 纸色、",[33,64,65],{},"#241F18"," 墨色与 ",[33,68,69],{},"#B23A2E"," 朱红，四角是 L 形朱线，数字键盘自己画，字体用衬线。它不追求“酷”，而是让一个偏底层的工具看起来像一本摊开的册子。",{"title":72,"searchDepth":73,"depth":73,"links":74},"",2,[75,76,77],{"id":14,"depth":73,"text":14},{"id":28,"depth":73,"text":28},{"id":55,"depth":73,"text":55},"mobile","移动",null,"md",true,[84,87,90,93,96,99],{"title":85,"description":86},"首扫与过滤","按 Int32 \u002F Int64 \u002F Float \u002F Double 扫描，再通过变大、变小、未变、变化逐步收敛。",{"title":88,"description":89},"模糊搜索","先对内存段做快照，再按差值条件多轮过滤，适合不知道确切数值的场景。",{"title":91,"description":92},"指针链","在指定范围内查找指针，用 BFS 追到模块基址，得到可复用的地址链。",{"title":94,"description":95},"地址簿","把常用地址与备注存进本地，下次进入游戏可以直接读取或改写。",{"title":97,"description":98},"变速","调整目标进程的时间倍率，用于单机场景下的节奏测试。",{"title":100,"description":101},"和纸界面","纸、墨、朱印三色，四角朱线、衬线字体与自绘键盘，尽量不像一个“黑客工具”。",[],{"github":104},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FDianMo",{},[107,110,113],{"label":108,"value":109},"数值类型","4 种",{"label":111,"value":112},"结果上限","5000 条",{"label":114,"value":115},"扫描器","1 个 CLI",3,"\u002Fprojects\u002Fdianmo",[119],"Android",[121,122],"wiredeck","lantai","设计 \u002F Android \u002F Native",{"title":6,"description":72},"dianmo",[127,128,129,130],"Kotlin","C++","libsu","Material 3","maintained","维护中","projects\u002Fdianmo","点墨是一个面向 Android 单机离线场景的内存调试工具。App 本身不持有 root，通过 libsu 拉起独立 native 扫描器，再做首扫、过滤、指针链与地址簿。","纸、墨、朱印，和一枚能读内存的悬浮窗。","DIANMO","2026","EHqWp3-AySgXtyuZr1kHEBTBgOexfK22X4QgwhtNX3w",{"id":140,"title":141,"accent":142,"body":143,"category":259,"categoryLabel":260,"cover":80,"description":72,"extension":81,"featured":261,"features":262,"gallery":281,"links":282,"meta":284,"metrics":285,"navigation":82,"order":294,"path":295,"platforms":296,"related":300,"role":302,"seo":303,"slug":304,"stack":305,"status":311,"statusLabel":132,"stem":312,"summary":313,"tagline":314,"titleEn":315,"year":316,"__hash__":317},"projects\u002Fprojects\u002Felectron-template.md","Electron 桌面模板","blue",{"type":9,"value":144,"toc":254},[145,148,155,166,169,248,251],[12,146,147],{"id":147},"为什么做这个模板",[16,149,150,151,154],{},"Electron 项目的重复劳动不在窗口本身，而在窗口之外：IPC 通道散落在各处、preload 越暴露越多、CSP 与导航拦截常常忘记加、更新链路只在真机上出问题。这个模板把这些约定提前落成目录结构和代码：主进程、preload、渲染进程各就各位，",[33,152,153],{},"shared\u002Fipc"," 是三者之间唯一的契约来源。",[16,156,157,158,161,162,165],{},"渲染层是 Vue 3.5 + Vite+，状态用 pinia，组件用 Naive UI，样式走 UnoCSS；构建、检查与格式化统一交给 ",[33,159,160],{},"vp","。主进程与渲染进程各自维护 tsconfig，",[33,163,164],{},"pnpm typecheck"," 一次跑完两侧。",[12,167,168],{"id":168},"值得说的细节",[170,171,172,187,200,213,226],"ul",{},[173,174,175,178,179,182,183,186],"li",{},[22,176,177],{},"通道没有手写字符串","：",[33,180,181],{},"channels.ts"," 定义常量表，主进程注册、preload 白名单与渲染层调用都引用常量；",[33,184,185],{},"contracts.ts"," 用通道作键，补一行映射就能得到三端类型约束。",[173,188,189,178,192,195,196,199],{},[22,190,191],{},"preload 只暴露六组方法",[33,193,194],{},"app \u002F window \u002F dialog \u002F system \u002F updater \u002F menu","，不把 ",[33,197,198],{},"ipcRenderer"," 交给页面；事件订阅同样走白名单。",[173,201,202,178,205,208,209,212],{},[22,203,204],{},"本地资源走 app:\u002F\u002F 协议",[33,206,207],{},"protocol.ts"," 校验协议与主机名并防路径穿越，命中不到的无扩展名路径回退 ",[33,210,211],{},"index.html","，深链不白屏。",[173,214,215,178,218,221,222,225],{},[22,216,217],{},"更新只信 HTTPS + sha512",[33,219,220],{},"updater.ts"," 在未打包时直接降级，联调要用明文源必须显式设置 ",[33,223,224],{},"ALLOW_INSECURE_UPDATE=1","。",[173,227,228,231,232,235,236,239,240,243,244,247],{},[22,229,230],{},"镜像注入放在 Node 脚本里","：pnpm 12 不会把 ",[33,233,234],{},".npmrc"," 导出给 ",[33,237,238],{},"pnpm run","，所以 ",[33,241,242],{},"install.mjs"," 与 ",[33,245,246],{},"dist.mjs"," 自己拼环境变量，安装和打包都不依赖 shell 前缀。",[12,249,250],{"id":250},"现状",[16,252,253],{},"作为团队新桌面项目的起点在持续维护。当前验证覆盖构建、启动与三平台产物生成；窗口布局、主题切换与图标渲染还没有做逐像素的视觉走查，Windows 与 Linux 也只验证了包内元数据，未在实机安装运行。",{"title":72,"searchDepth":73,"depth":73,"links":255},[256,257,258],{"id":147,"depth":73,"text":147},{"id":168,"depth":73,"text":168},{"id":250,"depth":73,"text":250},"desktop","桌面",false,[263,266,269,272,275,278],{"title":264,"description":265},"类型化 IPC","通道常量、请求与响应映射、preload 白名单共用 shared\u002Fipc，新增通道补一行映射，三端同时拿到类型约束。",{"title":267,"description":268},"安全基线","contextIsolation、sandbox 与 nodeIntegration 在 webPreferences 逐项声明，配套 CSP、导航拦截与 app:\u002F\u002F 协议防路径穿越。",{"title":270,"description":271},"自动更新","electron-updater 仅在打包后启用，强制 HTTPS 并校验 sha512，缺少校验值的更新包直接拒绝。",{"title":273,"description":274},"国内镜像安装","install:cn 注入 npmmirror 后安装依赖并补装 Electron 二进制，绕开 electron 45 不再自带 postinstall 的问题。",{"title":276,"description":277},"三平台打包","electron-builder 单一声明式配置源，输出 dmg、NSIS 与 AppImage\u002Fdeb，产物统一落在 release\u002F 且不进版本库。",{"title":279,"description":280},"浏览器降级","dev:renderer 脱离 Electron 启动渲染进程，bridge 自动切到 mock，同一份界面代码在浏览器里也能预览。",[],{"github":283},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FElectronTemplate",{},[286,289,291],{"label":287,"value":288},"进程模型","三端共享契约",{"label":267,"value":290},"逐项显式",{"label":292,"value":293},"打包目标","mac \u002F win \u002F linux",8,"\u002Fprojects\u002Felectron-template",[297,298,299],"macOS","Windows","Linux",[301,121],"wails3-template","模板设计与维护",{"title":141,"description":72},"electron-template",[306,307,308,309,310],"Electron","Vue 3","TypeScript","Vite+","electron-builder","active","projects\u002Felectron-template","基于 Electron 45 + Vue 3.5 + Vite+ 的桌面应用模板：主进程、preload 与渲染进程共用同一份 IPC 契约，CSP、sandbox、导航拦截与更新校验逐项显式开启，electron-builder 覆盖 macOS、Windows 与 Linux 打包。","把安全基线与类型化 IPC 先定好，克隆下来直接写业务。","ELECTRON \u002F DESKTOP TEMPLATE","持续维护","KiW95E0okJaylhyHaOdHloHck5X51yQy0oyZjzJmUxY",{"id":319,"title":320,"accent":142,"body":321,"category":392,"categoryLabel":393,"cover":80,"description":72,"extension":81,"featured":82,"features":394,"gallery":413,"links":414,"meta":415,"metrics":416,"navigation":82,"order":426,"path":427,"platforms":428,"related":431,"role":433,"seo":434,"slug":122,"stack":435,"status":311,"statusLabel":132,"stem":441,"summary":442,"tagline":443,"titleEn":444,"year":445,"__hash__":446},"projects\u002Fprojects\u002Flantai.md","兰台",{"type":9,"value":322,"toc":387},[323,326,333,344,347,382,384],[12,324,325],{"id":325},"为什么做兰台",[16,327,328,329,332],{},"大多数“全栈模板”把前后端放在两个仓库里：类型各写一份、请求层各封一套、部署要维护 Node 与 Go 两套运行时。兰台反过来做——",[22,330,331],{},"一个仓库、一个二进制、一份配置","，把多端交付的固定成本压到最低。",[16,334,335,336,339,340,343],{},"后端是 GoFrame 主服务与独立的更新分发服务；前台包括 Element Plus 管理端、Naive UI 云阁 Web、uni-app 移动端。三端构建产物先组装到 ",[33,337,338],{},"resource\u002Fpublic","，再由 ",[33,341,342],{},"gf build --ps"," 嵌入二进制。改动前端需要重新构建，这是单文件交付的代价，也是它最简单的地方。",[12,345,346],{"id":346},"几个关键取舍",[170,348,349,361,367,373],{},[173,350,351,178,354,243,357,360],{},[22,352,353],{},"双域 JWT 隔离",[33,355,356],{},"\u002Fapi\u002Fv1\u002Fadmin\u002F*",[33,358,359],{},"\u002Fapi\u002Fv1\u002Fapp\u002F*"," 使用不同的受众，管理端令牌不能打业务接口。",[173,362,363,366],{},[22,364,365],{},"goose 迁移而不是自动同步","：生产 DDL 必须可审计、可回滚；开发期才允许自动同步。",[173,368,369,372],{},[22,370,371],{},"更新服务独立部署","：APK 下载是长带宽、发布节奏独立，拆开后不影响业务 API。",[173,374,375,378,379,381],{},[22,376,377],{},"内嵌资源优先","：改了 ",[33,380,338],{}," 却没有重新构建，运行时会继续读旧资源——这是最容易踩的坑之一。",[12,383,250],{"id":250},[16,385,386],{},"兰台仍在持续迭代，主要精力放在移动端更新链路、权限模型与部署体验上。它是一个内部平台型项目，演示与接入需要单独沟通。",{"title":72,"searchDepth":73,"depth":73,"links":388},[389,390,391],{"id":325,"depth":73,"text":325},{"id":346,"depth":73,"text":346},{"id":250,"depth":73,"text":250},"platform","平台",[395,398,401,404,407,410],{"title":396,"description":397},"单仓多端","后端、管理端、云阁 Web 与移动端放在同一个仓库，共享类型、请求层与构建约定。",{"title":399,"description":400},"双域认证","管理端与业务端使用独立的 JWT 受众，令牌不能跨域使用，避免权限越界。",{"title":402,"description":403},"三段式权限","用“域:资源:操作”描述权限点，在线授权后实时生效，不需要重新登录。",{"title":405,"description":406},"独立更新分发","APK 与 wgt 的检测、灰度、签名下载与事件回收拆成独立服务，不占用业务 API。",{"title":408,"description":409},"可观测性","结构化日志、Prometheus 指标、操作审计与按日滚动日志，排障时能还原链路。",{"title":411,"description":412},"单文件部署","三端静态产物嵌入 Go 二进制，生产环境只需要二进制与一份配置文件。",[],{},{},[417,420,423],{"label":418,"value":419},"前台形态","3 端",{"label":421,"value":422},"交付物","1 个二进制",{"label":424,"value":425},"服务拆分","2 个服务",1,"\u002Fprojects\u002Flantai",[429,119,430],"Web","iOS",[432,121],"static-hub","架构 \u002F 全栈 \u002F 设计",{"title":320,"description":72},[436,437,307,438,439,440],"Go","GoFrame","uni-app","MySQL","Redis","projects\u002Flantai","兰台是 VaKao 的全栈单仓实践：GoFrame 主服务、独立更新分发、管理端、云阁 Web 与 uni-app 移动端。三端产物嵌入二进制，部署只需要一个文件与一份配置。","一套后端，三端前台，单文件交付。","LANTAI \u002F VAKAO PLATFORM","持续迭代","10rJAjyqG8ajsErfdpcTRKKfLzH8UFSu2x2k0OuyNa8",{"id":448,"title":449,"accent":450,"body":451,"category":488,"categoryLabel":489,"cover":80,"description":72,"extension":81,"featured":261,"features":490,"gallery":506,"links":507,"meta":509,"metrics":510,"navigation":82,"order":520,"path":521,"platforms":522,"related":524,"role":527,"seo":528,"slug":529,"stack":530,"status":131,"statusLabel":534,"stem":535,"summary":536,"tagline":537,"titleEn":538,"year":316,"__hash__":539},"projects\u002Fprojects\u002Frequest-interceptor.md","请求拦截与调试器","purple",{"type":9,"value":452,"toc":484},[453,457,460,470,473],[12,454,456],{"id":455},"为什么不用-devtools","为什么不用 DevTools",[16,458,459],{},"Chrome DevTools 已经能看请求，但“改一个响应再刷新”并不顺手：要么用本地代理，要么在代码里加断点。这个扩展把常用动作放进侧边栏：捕获、过滤、Mock、改包、重定向，规则可以保存和导入。",[16,461,462,463,243,466,469],{},"实现方式是在页面上下文里 Monkey Patch ",[33,464,465],{},"fetch",[33,467,468],{},"XMLHttpRequest","，扩展侧边栏通过消息通道读取记录。所有数据留在本地，不上传服务器。",[12,471,472],{"id":472},"边界",[170,474,475,478,481],{},[173,476,477],{},"只处理页面 JS 发起的请求，Service Worker、WebSocket 与部分跨域场景需要单独处理。",[173,479,480],{},"改包可能破坏签名或业务校验，规则默认关闭，命中时在列表里明确标记。",[173,482,483],{},"仅用于自己有权调试的页面与接口。",{"title":72,"searchDepth":73,"depth":73,"links":485},[486,487],{"id":455,"depth":73,"text":456},{"id":472,"depth":73,"text":472},"extension","扩展",[491,494,497,500,503],{"title":492,"description":493},"请求捕获","在页面上下文里替换 fetch 与 XMLHttpRequest，记录请求、响应与耗时。",{"title":495,"description":496},"过滤与搜索","按 URL、方法、状态码筛选，长列表里快速定位目标请求。",{"title":498,"description":499},"Mock 与改包","命中规则时直接返回本地响应，或修改请求头、请求体后再放行。",{"title":501,"description":502},"重定向","把请求转发到另一个地址，用于本地联调与环境切换。",{"title":504,"description":505},"规则导入导出","规则以 JSON 保存，可以在团队之间共享，也可以纳入版本管理。",[],{"github":508},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FRequestInterceptorDebugger",{},[511,514,517],{"label":512,"value":513},"捕获对象","fetch \u002F XHR",{"label":515,"value":516},"规则能力","Mock \u002F 改包 \u002F 重定向",{"label":518,"value":519},"数据位置","本地",6,"\u002Fprojects\u002Frequest-interceptor",[523],"Chrome",[525,526],"video-speed","vakao-ui","扩展开发",{"title":449,"description":72},"request-interceptor",[531,532,533],"Manifest V3","Monkey Patch","JavaScript","可用","projects\u002Frequest-interceptor","一个 Manifest V3 侧边栏扩展：Monkey Patch 页面 fetch\u002FXHR，做请求捕获、过滤、Mock、改包、重定向与规则导入导出。","在侧边栏里看清、改掉、重放每一个请求。","REQUEST INTERCEPTOR","UAK4oMg2N9SKZRk9sicTkKSfVxQ8WmAio502kwhFSxU",{"id":541,"title":542,"accent":450,"body":543,"category":392,"categoryLabel":592,"cover":80,"description":72,"extension":81,"featured":82,"features":593,"gallery":612,"links":613,"meta":615,"metrics":616,"navigation":82,"order":73,"path":626,"platforms":627,"related":629,"role":630,"seo":631,"slug":432,"stack":632,"status":311,"statusLabel":534,"stem":636,"summary":637,"tagline":638,"titleEn":639,"year":445,"__hash__":640},"projects\u002Fprojects\u002Fstatic-hub.md","静态资源中心",{"type":9,"value":544,"toc":587},[545,548,551,554,556,582,584],[12,546,547],{"id":547},"它解决什么问题",[16,549,550],{},"小团队经常把图片、APK、安装包、临时文件散落在服务器目录、网盘和聊天记录里。静态资源中心把这些东西收进一个可检索的控制台：文件有分类、有缩略图、有分享链接，App 更新包也有独立的发布状态。",[16,552,553],{},"后端是 NestJS + SQLite，前端是 Vue 3 + Naive UI。SQLite 的选择很务实：单机静态资源站，零外部依赖，拷一个库文件就能备份；代价是并发写和大数据量受限。",[12,555,168],{"id":168},[170,557,558,564,570,576],{},[173,559,560,563],{},[22,561,562],{},"文件系统是真相，数据库是索引","：启动全量扫描、定时增量、根目录变更触发刷新，避免“库里有、盘上没有”。",[173,565,566,569],{},[22,567,568],{},"分片上传 + SHA-256 合并校验","：APK 与视频动辄数百 MB，整包上传容易断；分片让失败只影响一个块。",[173,571,572,575],{},[22,573,574],{},"分享用 HMAC 短期令牌","：链接本身不暴露真实路径，密码不落明文。",[173,577,578,581],{},[22,579,580],{},"更新中心是独立模块","：与兰台的更新服务功能重叠，长期需要收敛；当前保留两套实现是历史包袱。",[12,583,250],{"id":250},[16,585,586],{},"作为内部工具持续使用中。后台涉及真实文件与账号信息，官网只展示结构与能力，不公开管理入口。",{"title":72,"searchDepth":73,"depth":73,"links":588},[589,590,591],{"id":547,"depth":73,"text":547},{"id":168,"depth":73,"text":168},{"id":250,"depth":73,"text":250},"工具",[594,597,600,603,606,609],{"title":595,"description":596},"多根目录","一个后台管理多个资源根目录，按分类浏览、搜索、排序，文件系统仍是最终事实。",{"title":598,"description":599},"分片上传","大文件切 5MB 分片，支持断点续传与合并校验，弱网下不用整包重来。",{"title":601,"description":602},"分享链接","单文件或多文件聚合分享，支持有效期、访问次数与访问密码，链接不暴露真实路径。",{"title":604,"description":605},"图片处理","基于 Sharp 的缩放、格式转换与磁盘缩略图缓存，避免每次请求都重新解码。",{"title":607,"description":608},"更新中心","APK 上传、四态发布、灰度分桶、强更与回滚，客户端按设备稳定命中。",{"title":610,"description":611},"审计与指标","登录、上传、删除、发布、分享等关键动作落审计日志，指标页看 QPS 与存储量。",[],{"github":614},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FVakaoStaticHub",{},[617,620,623],{"label":618,"value":619},"上传方式","5MB 分片",{"label":621,"value":622},"内容校验","SHA-256",{"label":624,"value":625},"更新状态","4 态","\u002Fprojects\u002Fstatic-hub",[429,628],"API",[122,526],"全栈 \u002F 运维",{"title":542,"description":72},[633,634,307,635,308],"NestJS","SQLite","Sharp","projects\u002Fstatic-hub","一个面向小团队的静态资源管理系统：多根目录文件管理、分片上传、图片处理、分享链接、随机图与占位图，以及 App 在线更新中心。","把文件、分享与更新包放进一个可检索的控制台。","VAKAO STATIC HUB","hCHHdJuV2ZAilDYjYjGkjP4xf7FnQHtvmREG9x3UGQM",{"id":642,"title":643,"accent":142,"body":644,"category":701,"categoryLabel":702,"cover":80,"description":72,"extension":81,"featured":261,"features":703,"gallery":712,"links":713,"meta":715,"metrics":716,"navigation":82,"order":726,"path":727,"platforms":728,"related":730,"role":731,"seo":732,"slug":526,"stack":733,"status":311,"statusLabel":132,"stem":737,"summary":738,"tagline":739,"titleEn":740,"year":316,"__hash__":741},"projects\u002Fprojects\u002Fvakao-ui.md","VaKao UI",{"type":9,"value":645,"toc":697},[646,649,656,692,694],[12,647,648],{"id":648},"为什么自己写",[16,650,651,652,655],{},"团队项目多了之后，每个仓库都会复制一份 axios 封装：有的处理 401，有的不处理；有的解信封，有的不解。",[33,653,654],{},"@vakao-ui\u002F*"," 把这些约定收进三个小包，项目只依赖接口，不依赖实现细节。",[170,657,658,669,677,685],{},[173,659,660,178,665,668],{},[22,661,662],{},[33,663,664],{},"@vakao-ui\u002Faxios",[33,666,667],{},"createClient"," 一次性配置 baseURL、超时、鉴权头、刷新与错误出口；401 只刷新一次，失败的请求排队重放。",[173,670,671,676],{},[22,672,673],{},[33,674,675],{},"@vakao-ui\u002Fsocket-system","：把连接、重连、房间恢复、消息编解码与错误处理收进一个无框架的客户端，测试用假传输与虚拟时钟。",[173,678,679,684],{},[22,680,681],{},[33,682,683],{},"@vakao-ui\u002Fscripts-utils","：统一终端颜色、图标、横幅与日志，让不同项目的构建输出看起来像一家人。",[173,686,687,691],{},[22,688,689],{},[33,690,526],{},"：Vue 3 + TypeScript 组件库，承接团队页面里反复出现的交互与视觉约定。",[12,693,250],{"id":250},[16,695,696],{},"内部使用为主，API 仍在收敛。它们不追求成为通用框架，只解决 VaKao 项目里反复出现的那几个问题。",{"title":72,"searchDepth":73,"depth":73,"links":698},[699,700],{"id":648,"depth":73,"text":648},{"id":250,"depth":73,"text":250},"library","开源库",[704,706,709],{"title":667,"description":705},"统一信封解包、401 单飞刷新、重复请求取消与全局 loading 计数。",{"title":707,"description":708},"类型安全 Socket","连接管理、自动重连、房间恢复、标准化消息与统一错误出口。",{"title":710,"description":711},"脚本工具","终端颜色、图标、ASCII 横幅、日志与常用工具函数，供各项目构建脚本复用。",[],{"github":714},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FVakaoUI",{},[717,720,723],{"label":718,"value":719},"包数量","4 个",{"label":721,"value":722},"请求层","0.0.2",{"label":724,"value":725},"框架绑定","无",7,"\u002Fprojects\u002Fvakao-ui",[429,729],"Node",[122,432],"库设计与维护",{"title":643,"description":72},[308,734,735,736],"axios","Socket.IO","CLI","projects\u002Fvakao-ui","团队内部的前端基础设施：@vakao-ui\u002Faxios 统一请求与 401 刷新，@vakao-ui\u002Fsocket-system 提供类型安全的 Socket 协议，@vakao-ui\u002Fscripts-utils 收敛构建脚本的终端输出，vakao-ui 提供 Vue 3 组件。","四个小库，把团队项目里重复的脏活收掉。","VAKAO UI \u002F INTERNAL LIBS","hH3E7BtjcZOGcjZQp2rWdVHUw7oMuii_1uCGoIAYZT8",{"id":743,"title":744,"accent":142,"body":745,"category":488,"categoryLabel":489,"cover":80,"description":72,"extension":81,"featured":261,"features":791,"gallery":804,"links":805,"meta":807,"metrics":808,"navigation":82,"order":817,"path":818,"platforms":819,"related":821,"role":527,"seo":822,"slug":525,"stack":823,"status":131,"statusLabel":534,"stem":825,"summary":826,"tagline":827,"titleEn":828,"year":316,"__hash__":829},"projects\u002Fprojects\u002Fvideo-speed.md","视频速度控制器",{"type":9,"value":746,"toc":787},[747,750,753,760,763],[12,748,749],{"id":749},"一个小而完整的扩展",[16,751,752],{},"视频网站大多有倍速菜单，但操作路径长：点开菜单、选倍速、再关掉。这个扩展把最常用的动作变成键盘：Z 减速、X 加速、C 复位，数字键直接输入目标倍速。",[16,754,755,756,759],{},"实现上是 Manifest V3 + 内容脚本，监听页面里的 HTML5 ",[33,757,758],{},"\u003Cvideo>","，不依赖任何后端。全屏时用一个轻量浮层提示当前倍速，几秒后自动消失。",[12,761,762],{"id":762},"设计取舍",[170,764,765,775,781],{},[173,766,767,770,771,774],{},[22,768,769],{},"不做站点适配清单","：优先操作标准 ",[33,772,773],{},"video"," 元素，站点自定义播放器需要单独处理。",[173,776,777,780],{},[22,778,779],{},"不接管所有键盘","：只在视频获得焦点或用户主动触发时响应，避免和站点快捷键打架。",[173,782,783,786],{},[22,784,785],{},"权限最小化","：只申请必要的站点访问权限，不读取页面内容上传。",{"title":72,"searchDepth":73,"depth":73,"links":788},[789,790],{"id":749,"depth":73,"text":749},{"id":762,"depth":73,"text":762},[792,795,798,801],{"title":793,"description":794},"快捷键","Z 减速、X 加速、C 复位，不离开画面就能调。",{"title":796,"description":797},"数字直输","直接键入倍速数字，适合需要精确 1.25× \u002F 1.75× 的场景。",{"title":799,"description":800},"预设面板","弹窗里提供常用倍速，点一下即可应用。",{"title":802,"description":803},"全屏浮层","全屏时在角落短暂显示当前倍速，不打断观看。",[],{"github":806},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FVideoSpeedControl",{},[809,812,815],{"label":810,"value":811},"核心操作","键盘优先",{"label":813,"value":814},"覆盖范围","HTML5 视频",{"label":816,"value":725},"后端",5,"\u002Fprojects\u002Fvideo-speed",[523,820],"Edge",[529,526],{"title":744,"description":72},[531,533,824],"HTML\u002FCSS","projects\u002Fvideo-speed","一个 Manifest V3 浏览器扩展：Z \u002F X \u002F C 快捷键、数字直输、预设面板与全屏浮层提示，把视频倍速从菜单里解放出来。","给全网 HTML5 视频一个统一的倍速键盘。","VIDEO SPEED CONTROL","ZUuBRWNBJ1-Yfv2K5Mq5dK0N7yqthk4COJdIXLQtKjI",{"id":831,"title":832,"accent":7,"body":833,"category":259,"categoryLabel":260,"cover":80,"description":72,"extension":81,"featured":261,"features":949,"gallery":968,"links":969,"meta":971,"metrics":972,"navigation":82,"order":980,"path":981,"platforms":982,"related":983,"role":302,"seo":984,"slug":301,"stack":985,"status":311,"statusLabel":132,"stem":987,"summary":988,"tagline":989,"titleEn":990,"year":137,"__hash__":991},"projects\u002Fprojects\u002Fwails3-template.md","Wails3 桌面模板",{"type":9,"value":834,"toc":944},[835,837,852,862,864,935,937],[12,836,147],{"id":147},[16,838,839,840,843,844,847,848,851],{},"Wails v2 的项目里，Go 与前端的边界通常是手写 DTO 加口口相传的约定：字段改了前端不知道，事件名拼错只在运行时暴露。这个模板把边界收进代码：Go 侧的 ",[33,841,842],{},"internal\u002Fcontract"," 是唯一模型来源，",[33,845,846],{},"wails3 generate bindings"," 产出前端类型，",[33,849,850],{},"frontend\u002Fbindings"," 提交进仓库，漂移由脚本和 CI 一起拦。",[16,853,854,855,857,858,861],{},"前端沿用团队熟悉的一套：Vue 3.5、Naive UI、UnoCSS 与 Vite+ 的 ",[33,856,160],{}," 工具链；桌面能力通过 ",[33,859,860],{},"frontend\u002Fsrc\u002Fbridge"," 单层封装，事件订阅与错误归一化都只在这一层出现。",[12,863,168],{"id":168},[170,865,866,879,897,911,921],{},[173,867,868,178,871,874,875,878],{},[22,869,870],{},"CLI 版本先过门禁",[33,872,873],{},"scripts\u002Flib\u002Fwails.mjs"," 校验 ",[33,876,877],{},"wails3"," 不低于 v3.1.0，低于直接中止，避免旧版生成的 bindings 与契约不兼容。",[173,880,881,884,885,888,889,892,893,896],{},[22,882,883],{},"错误只有一种形状","：Go 侧统一返回 ",[33,886,887],{},"*contract.AppError","，经 ",[33,890,891],{},"MarshalError"," 变成 ",[33,894,895],{},"{code,message,details}","；前端加上 15s 超时与取消，再按 code 分支。",[173,898,899,902,903,906,907,910],{},[22,900,901],{},"图标是构建期校验的","：图标类名集中在 ",[33,904,905],{},"frontend\u002Fsrc\u002Ficons.ts","，UnoCSS safelist 由该表生成，",[33,908,909],{},"check-icons.mjs"," 同时校验集合里存在、产物 CSS 里真有规则。",[173,912,913,916,917,920],{},[22,914,915],{},"关窗不等于退出","：托盘保留进程，只有托盘菜单的“退出”才结束；窗口几何写入同一份 ",[33,918,919],{},"settings.json","，显示器变化时做可见性校验。",[173,922,923,926,927,930,931,934],{},[22,924,925],{},"任务取消走 context","：演示任务每步检查 ",[33,928,929],{},"ctx.Err()","，取消后推送 ",[33,932,933],{},"cancelled","，前端拿到的是事件而不是异常。",[12,936,250],{"id":250},[16,938,939,940,943],{},"模板刚落地，macOS 上已验证 ",[33,941,942],{},".app"," 与 DMG 产出；Windows 与 Linux 打包只跑过 CI 配置，未在实机安装，代码签名与公证仍留着入口没接证书。自动更新尚未实现，代码里没有 updater 接入点。",{"title":72,"searchDepth":73,"depth":73,"links":945},[946,947,948],{"id":147,"depth":73,"text":147},{"id":168,"depth":73,"text":168},{"id":250,"depth":73,"text":250},[950,953,956,959,962,965],{"title":951,"description":952},"Go 单进程","main.go 用 go:embed 打包前端产物，Wails v3 承载系统 WebView，不起额外的 Node 运行时。",{"title":954,"description":955},"契约单一来源","internal\u002Fcontract 定义模型、事件与结构化错误，前端类型全部来自生成的 bindings，不手写 DTO。",{"title":957,"description":958},"bindings 防漂移","frontend\u002Fbindings 入库，check:bindings 重新生成并比对，CI 用 git diff 拦住忘记提交的契约变更。",{"title":960,"description":961},"托盘与窗口状态","关窗只收进托盘，托盘菜单提供显示主窗口、设置与退出；窗口位置尺寸写入 settings.json，拔掉外接屏后回落居中。",{"title":963,"description":964},"可取消任务","CapabilitiesService.RunDemoTask 用 context.Context 演示取消，前端取消会中断 Go 循环并收到 cancelled 事件。",{"title":966,"description":967},"双门禁","check:fe 串起类型检查、lint、格式化、图标校验与 bindings 漂移，check:go 跑 go vet、go test 与 golangci-lint。",[],{"github":970},"https:\u002F\u002Fgithub.com\u002FRouarn\u002FWails3Template",{},[973,975,977],{"label":974,"value":951},"运行时",{"label":976,"value":842},"契约来源",{"label":978,"value":979},"CLI 门禁","≥ v3.1.0",9,"\u002Fprojects\u002Fwails3-template",[297,298,299],[304,121],{"title":832,"description":72},[436,986,307,308,309],"Wails v3","projects\u002Fwails3-template","基于 Wails v3 + Vite+ 的桌面应用模板：Go 单进程承载系统 WebView，internal\u002Fcontract 是唯一模型来源，前端 bindings 由 wails3 generate 生成并入库，配合 CLI 版本门禁与前后端双门禁。","Go 单进程承载 WebView，前端类型从 Go 契约直接生成。","WAILS3 \u002F DESKTOP TEMPLATE","gTmxPkxf--qxB8CHrYeWBBh6YiOtxT_d70xqWzVkl-U",{"id":993,"title":994,"accent":995,"body":996,"category":259,"categoryLabel":260,"cover":80,"description":72,"extension":81,"featured":82,"features":1045,"gallery":1064,"links":1065,"meta":1069,"metrics":1070,"navigation":82,"order":1079,"path":1080,"platforms":1081,"related":1082,"role":1083,"seo":1084,"slug":121,"stack":1085,"status":1088,"statusLabel":1089,"stem":1090,"summary":1091,"tagline":1092,"titleEn":1093,"year":137,"__hash__":1094},"projects\u002Fprojects\u002Fwiredeck.md","WireDeck","yellow",{"type":9,"value":997,"toc":1040},[998,1002,1009,1012,1015,1035,1037],[12,999,1001],{"id":1000},"为什么做-wiredeck","为什么做 WireDeck",[16,1003,1004,1005,1008],{},"Android 自带的“无线调试”很好用，但门槛不低：找 IP、记端口、输入配对码，再敲一堆 ",[33,1006,1007],{},"adb"," 命令。WireDeck 把这些步骤收进一个窗口：扫码连接，然后安装、卸载、传文件、看日志都不需要命令行。",[16,1010,1011],{},"技术上是 Wails v2 + Go + Vue 3：Go 负责 adb、进程、文件与 scrcpy 编排，Vue 负责界面。选择 Wails 而不是 Electron，是为了更小的包体和更直接的系统调用；代价是跨平台细节要自己填。",[12,1013,1014],{"id":1014},"两个真实的坑",[170,1016,1017,1026],{},[173,1018,1019,1022,1023,225],{},[22,1020,1021],{},"Windows 子进程必须隐藏窗口","：GUI 程序调用 adb 会反复弹 CMD，所有子进程都要加 ",[33,1024,1025],{},"HideWindow + CREATE_NO_WINDOW",[173,1027,1028,1034],{},[22,1029,1030,1033],{},[33,1031,1032],{},"\u002Freleases\u002Flatest"," 会忽略 prerelease","：下载链接使用显式 tag，避免 404。",[12,1036,250],{"id":250},[16,1038,1039],{},"v1.0.1 已发布，目前进入维护暂停；有问题提交 Issue，看到后会恢复维护。macOS 为 ad-hoc 签名、未公证，首次打开需要右键 → 打开。",{"title":72,"searchDepth":73,"depth":73,"links":1041},[1042,1043,1044],{"id":1000,"depth":73,"text":1001},{"id":1014,"depth":73,"text":1014},{"id":250,"depth":73,"text":250},[1046,1049,1052,1055,1058,1061],{"title":1047,"description":1048},"扫码配对","手机扫一下电脑上的二维码就能连上，也可以手动输入配对码。",{"title":1050,"description":1051},"应用管理","应用列表、卸载、启动、强停、清数据、导出 APK，文件名优先中文名。",{"title":1053,"description":1054},"文件传输","双栏管理、拖放添加、批量推送与拉取，截图可以直接保存到电脑。",{"title":1056,"description":1057},"日志与 Shell","按应用过滤 logcat，自动识别崩溃与 ANR；常用命令有快捷入口。",{"title":1059,"description":1060},"投屏控制","内置 scrcpy，一键在电脑上操作手机，窗口标题带设备名。",{"title":1062,"description":1063},"开箱即用","不要求安装 Android Studio；adb、aapt2、scrcpy 都随应用打包。",[],{"site":1066,"github":1067,"download":1068},"https:\u002F\u002Fwiredeck.woyuxiaji.cn","https:\u002F\u002Fgithub.com\u002FRouarn\u002FWireDeck","https:\u002F\u002Fgithub.com\u002FRouarn\u002FWireDeck\u002Freleases",{},[1071,1074,1076],{"label":1072,"value":1073},"正式版","v1.0.1",{"label":393,"value":1075},"macOS \u002F Windows",{"label":1077,"value":1078},"内置工具","adb \u002F aapt2 \u002F scrcpy",4,"\u002Fprojects\u002Fwiredeck",[297,298],[125,432],"产品 \u002F 桌面端 \u002F 发布",{"title":994,"description":72},[1086,436,307,1007,1087],"Wails","scrcpy","paused","维护暂停","projects\u002Fwiredeck","一个把无线 ADB 包进图形界面的桌面工具：扫码配对、应用管理、APK 安装、文件传输、实时日志与 Shell。内置 adb、aapt2 与 scrcpy，不需要 Android SDK。","在电脑上无线管理安卓手机，开箱即用。","WIREDECK","svPInLxMWRhKtFjfqUXvUBMnCBZy9Nx9MnJkAZX-MLk",1793876034605]