Bilibili-Evolved 夜间模式计划时段:时间调度机制与源码实现解析
Bilibili-Evolved 夜间模式计划时段时间调度机制与源码实现解析【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-EvolvedBilibili-Evolved 是一款开源的哔哩哔哩增强脚本其中的「夜间模式计划时段」组件允许用户设定一个时间范围让夜间模式在该时间段内自动开启、离开该时间段后自动关闭从而避免手动反复切换主题。本文以该组件的说明文档schedule/index.md为主体结合其 TypeScript 实现 与「夜间模式」主组件源码完整讲解配置方法、跨天时间判断逻辑、自动切换调度原理以及与其他夜间模式组件的配合与注意事项。功能概述按时间段自动开关夜间模式「夜间模式计划时段」darkModeSchedule是 Bilibili-Evolved 夜间模式体系下的一个调度型组件。它的核心能力是用户指定一个时间段如18:00至6:00当系统时间进入该时间段时自动开启夜间模式当系统时间离开该时间段时自动关闭夜间模式。从源码中的组件定义可以看出该组件归属于style与general两个标签分类注册名为darkModeSchedule显示名为「夜间模式计划时段」export const component defineComponentMetadata({ name: darkModeSchedule, displayName: 夜间模式计划时段, tags: [componentsTags.style, componentsTags.general], entry: ({ settings }) fullyLoaded(() checkTime(settings)), urlExclude: darkExcludes, options, })见 schedule/index.ts其中entry通过fullyLoaded包装调度函数确保页面核心内容完全加载后才开始首次时间检查urlExclude则复用了夜间模式统一的排除页面列表darkExcludes在这些页面上组件不会生效。配置说明时间段参数的格式与默认值该组件的唯一配置项是range时间段其元数据定义如下const options defineOptionsMetadata({ range: { defaultValue: { start: 18:00, end: 6:00, }, displayName: 时间段, validator: (range: Rangestring) { const { start, end } range const regex /^(\d{1,2}):(\d{1,2})$/ if (!regex.test(start) || !regex.test(end)) { return null } const startTime new ScheduleTime(range.start) const endTime new ScheduleTime(range.end) return { start: startTime.toString(), end: endTime.toString(), } }, }, })见 schedule/index.ts由此可以得到以下配置要点要点说明默认时间段18:00至6:00晚上 18 点到次日早上 6 点时间格式HH:mm或H:mm由正则/^(\d{1,2}):(\d{1,2})$/校验小时允许 1~2 位数字、分钟允许 1~2 位数字格式校验不符合正则的输入会返回null校验失败无法保存输入规范化校验通过后时间会被解析并重新格式化如6:0会规范化为06:00返回保证配置存储格式统一需要注意的是校验正则本身并不严格限制小时在 0~23、分钟在 0~59 的范围内但ScheduleTime的解析逻辑会对越界值进行规范化处理详见下一节因此即使输入了如25:70这样的值也会被折算为合法的时钟时间。时间解析与规范化ScheduleTime 类组件实现的核心是一个轻量的时间工具类ScheduleTime负责完成字符串解析、数值规范化与时间比较。其构造函数支持三种调用方式class ScheduleTime { constructor(...args: [] | [string] | [number, number]) { if (args.length 0) { const now new Date() this.hour now.getHours() this.minute now.getMinutes() } else if (args.length 1) { const [text] args ;[this.hour, this.minute] text .split(:) .slice(0, 2) .map(it ScheduleTime.validatePart(it)) this.normalize() } else if (args.length 2) { ;[this.hour, this.minute] args } } }见 schedule/index.ts无参数取当前系统时间小时 分钟用于现在的判断一个字符串形如18:00先按冒号分割用validatePart逐段解析为数字再调用normalize()规范化两个数字直接以(hour, minute)赋值。validatePart只接受 0~59 之间的数字其余返回null。而normalize()会把越界的分钟折算进位/借位到小时、把越界的小时折算到 0~23 区间normalize() { while (this.minute 0) { this.minute 60; this.hour - 1 } while (this.minute 60) { this.minute - 60; this.hour 1 } while (this.hour 0) { this.hour 24 } while (this.hour 24) { this.hour - 24 } }见 schedule/index.ts此外toString()会将时间统一输出为补零的HH:mm格式这正是配置项校验时用于规范化返回值的依据。跨天时间段判断结束时间小于起始时间视为次日文档中特别强调结束时间小于起始时间时将视为次日。例如18:00至6:00表示晚上 18:00 到次日 6:00。这一语义由isInRange方法实现isInRange(start: ScheduleTime, end: ScheduleTime) { if (start.equals(end)) { return false } let inRange this.greaterThan(start) this.lessThan(end) if (start.greaterThan(end)) { inRange this.greaterThan(start) || this.lessThan(end) } const result inRange || this.equals(start) return result }见 schedule/index.ts其判断逻辑可以拆解为三种情况场景判断方式示例起始时间等于结束时间直接判定为不在范围内false避免全天恒开18:00~18:00起始时间小于结束时间当天内当前时间必须同时大于起始、小于结束6:00~18:00起始时间大于结束时间跨天当前时间大于起始或小于结束二者满足其一即可18:00~6:00另外无论哪种情况只要当前时间恰好等于起始时间this.equals(start)也会被判定为在范围内保证进入时间点能即时生效。这种起始点闭区间、结束点开区间的语义让跨天场景如夜晚睡眠时段无需区分日期即可正确工作。自动切换的调度机制checkTime 与定时器组件的运行核心是checkTime函数它完成三件事判断当前是否处于时段内、同步夜间模式开关状态、安排下一次检查的定时器const checkTime (settings: ComponentSettingsOptions) { const start new ScheduleTime(settings.options.range.start) const end new ScheduleTime(settings.options.range.end) const now new ScheduleTime() const useDarkMode now.isInRange(start, end) const darkModeSettings getComponentSettings(darkMode) if (darkModeSettings.enabled ! useDarkMode) { darkModeSettings.enabled useDarkMode } let timeout 0 if (useDarkMode) { timeout ScheduleTime.millisecondsBefore(end) } else { timeout ScheduleTime.millisecondsBefore(start) } if (timeout ! 0) { setTimeout(() checkTime(settings), timeout) } }见 schedule/index.ts整个调度流程如下构造start、end、now三个时间点调用isInRange判断当前是否应处于夜间模式通过getComponentSettings(darkMode)获取「夜间模式」主组件的设置对象若其enabled状态与判断结果不一致则直接写入新的状态——这一写操作会触发夜间模式主组件的启用/卸载进而完成主题切换依据当前所处状态用millisecondsBefore计算出距离下一个切换点结束时点或开始时点的毫秒数用setTimeout安排下一次checkTime调用形成检查—休眠—再检查的循环timeout 0时不再递归调度例如时间已精确到达切换点且无后续剩余时间避免空转。millisecondsBefore负责精确计算距离目标时间还有多少毫秒并在跨天时自动加上一整天static millisecondsBefore(time: ScheduleTime) { const now new ScheduleTime() const nowSeconds new Date().getSeconds() const currentMilliseconds 1000 * (now.hour * 3600 now.minute * 60 nowSeconds) const targetMilliseconds 1000 * (time.hour * 3600 time.minute * 60) let result targetMilliseconds - currentMilliseconds if (now.greaterThan(time) || (now.equals(time) nowSeconds ! 0)) { result 24 * 3600 * 1000 } return result }见 schedule/index.ts这里将时间统一折算为当天零时起的秒数再求差若目标时间已过或恰好等于但秒数不为零则补上 24 小时从而保证定时器总是指向下一次切换点而非过去的某个时刻。这种基于setTimeout而非轮询的设计使组件在页面运行期间几乎不消耗额外资源。与夜间模式主组件的协作关系「夜间模式计划时段」本身并不直接修改页面样式它只是调度器真正的主题切换由「夜间模式」主组件darkMode完成。主组件的add/remove逻辑会执行以下动作见 dark-mode/index.ts向document.body添加/移除darkclass这是所有暗色样式生效的总开关写入localStorage的pbp_theme_v4键值为b表示暗色保证主题状态可持久化同步维护页面meta nametheme-color与meta namecolor-scheme标签让浏览器地址栏配色与页面渲染模式与夜间模式保持一致。主组件还提供了一项「提前注入」插件能力在页面内容加载阶段就依据设置提前添加darkclass减少首屏短暂白屏的闪烁问题见 dark-mode/index.ts。因此当计划时段组件通过写darkMode.enabled触发切换时整个主题系统会按既有链路平滑生效。使用注意事项文档明确指出请勿和「夜间模式跟随系统」一同使用。其原因是两个组件都以自动决定darkMode.enabled为职责会互相覆盖对方的状态。对比两者实现「夜间模式跟随系统」darkModeFollowSystem通过matchMedia((prefers-color-scheme: dark))监听操作系统的亮/暗主题并在系统主题变化时同步切换见 follow-system/index.ts「夜间模式计划时段」则完全依据用户设定的时钟区间判断。若同时启用系统主题变化与时间区间会争夺开关控制权导致夜间模式状态在两个来源间反复横跳。此外文档还提醒在某些浏览器如 Microsoft Edge中「跟随系统」仅同步浏览器自身的亮/暗主题而非操作系统设置。因此实际使用时应二选一追求跟光线走选跟随系统追求固定作息选计划时段。另一个需要留意的点是排除页面darkExcludes列表见 dark-urls.ts排除了投稿中心、创作平台、直播剪辑、安全中心等页面这些页面要么更新频繁难以及时适配要么使用频率低计划时段组件在这些页面不会执行自动切换。实战配置示例在 Bilibili-Evolved 的设置面板中启用「夜间模式计划时段」组件后只需配置一个「时间段」选项即可夜间作息默认起始18:00结束6:00——适合默认配置覆盖整个夜间白天禁用例如起始22:00结束8:00让深夜到清晨自动保持暗色全天候亮色将起始与结束设为同一时间如0:00~0:00isInRange会判定为恒不在范围内夜间模式始终保持关闭。配置输入会经过正则校验与ScheduleTime规范化即使输入6:0也会被标准化为06:00后保存无需担心格式问题。若想进一步了解夜间模式样式的编写规范、配色建议与排除列表维护方式可阅读夜间模式模块的 README 及其对应的 index.md。【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

3分钟上手douyinhelper:免费下载你的第一个抖音视频(附安装步骤)

3分钟上手douyinhelper:免费下载你的第一个抖音视频(附安装步骤)

3分钟上手douyinhelper:免费下载你的第一个抖音视频(附安装步骤) 【免费下载链接】douyinhelper 抖音批量下载助手 项目地址: https://gitcode.com/gh_mirrors/do/douyinhelper douyinhelper(抖音批量下载助手)…

2026/9/19 16:51:34 阅读更多 →
Wand-Enhancer:WeMod 本地补丁与手机远程面板,5 个开关配置与踩坑记录

Wand-Enhancer:WeMod 本地补丁与手机远程面板,5 个开关配置与踩坑记录

Wand-Enhancer:WeMod 本地补丁与手机远程面板,5 个开关配置与踩坑记录 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand…

2026/9/19 16:50:34 阅读更多 →
如何快速构建qmcdump解密工具:makefile与make install编译完整教程

如何快速构建qmcdump解密工具:makefile与make install编译完整教程

如何快速构建qmcdump解密工具:makefile与make install编译完整教程 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdum…

2026/9/19 16:50:34 阅读更多 →

最新新闻

SpringBoot+Vue智慧家政系统实战:调度引擎与可信服务闭环

SpringBoot+Vue智慧家政系统实战:调度引擎与可信服务闭环

简介:本资源是一篇面向计算机专业本科生或初级Java全栈开发者的毕业设计类论文,聚焦智慧社区场景下的家政服务系统实现,解决传统家政服务信息不对称、响应滞后、管理低效等现实问题。全文基于SpringBootVue的B/S架构展开,涵盖系统…

2026/9/19 17:51:00 阅读更多 →
淋巴结生发中心B细胞障碍,把 Claude Code 的 Base URL 改到 TaoToken 后拆解空间多组学图谱

淋巴结生发中心B细胞障碍,把 Claude Code 的 Base URL 改到 TaoToken 后拆解空间多组学图谱

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 17:51:00 阅读更多 →
Gollum网页编辑器实战:在线编辑、拖拽上传与即时预览全体验

Gollum网页编辑器实战:在线编辑、拖拽上传与即时预览全体验

Gollum网页编辑器实战:在线编辑、拖拽上传与即时预览全体验 【免费下载链接】gollum A simple, Git-powered wiki with a local frontend and support for many kinds of markup and content. 项目地址: https://gitcode.com/gh_mirrors/go/gollum Gollum 是…

2026/9/19 17:51:00 阅读更多 →
私有Scheme调起失败?heytapbrowser跳转链路全解析

私有Scheme调起失败?heytapbrowser跳转链路全解析

最近一期投放数据复盘时,技术群里扔过来一个链接,说某渠道的归因回调成功率掉到了六成,用户点了落地页里的按钮,有一半概率没反应。我顺着后端打点日志查,发现回传链接里反复出现一条backurl参数,URL解码之…

2026/9/19 17:51:00 阅读更多 →
Claude Mythos Preview 只走 Project Glasswing,TaoToken 能统一日常 Claude 通道吗?

Claude Mythos Preview 只走 Project Glasswing,TaoToken 能统一日常 Claude 通道吗?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 17:51:00 阅读更多 →
MaxKey集成JeecgBoot实现单点登录:OAuth2统一身份认证实战

MaxKey集成JeecgBoot实现单点登录:OAuth2统一身份认证实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 17:50:00 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介:面向机器学习、深度学习与数据建模学习者的一份完整研究文献,聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本,系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程,展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型,在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志,发现loss从凌晨两点就开始往上爬,一路从0.8涨到1.35,整整六个小时没人发现。那六个小时的训练不仅白跑,还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud 🌤️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/19 3:59:36 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/19 3:53:08 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/19 4:02:43 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →