Bilibili-Evolved BV 号转换组件深度解析:AV/BV 号展示与链接复制实现指南
Bilibili-Evolved BV 号转换组件深度解析AV/BV 号展示与链接复制实现指南【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved本文基于 Bilibili-Evolved哔哩哔哩增强脚本开源仓库聚焦「BV 号转换」功能组件。该组件会在功能面板Widgets 面板中实时展示当前播放视频的 AV 号与 BV 号并支持一键复制为可跳转链接。文章将结合 组件源码 与 组件视图 逐层拆解其注册方式、运行条件、ID 抓取策略、链接构造规则与复制逻辑并延伸讲解videoChange事件、hasVideo判断等底层支撑机制帮助读者理解该增强脚本组件化的完整实现范式。功能概述在功能面板中显示视频的 AV 号和 BV 号官方文档对「BV 号转换」功能的描述十分精炼仅一句话在功能面板中显示视频的 AV 号和 BV 号.这一定位准确概括了组件的核心职责作为 Bilibili-Evolved 众多「视频」类组件之一它并不修改页面样式或注入新行为而是以挂件Widget的形式出现在功能面板中为播放页用户提供两个高频实用能力实时展示当前视频的 AV 号av前缀与 BV 号BV前缀一键复制指定 ID 对应的可跳转链接https://www.bilibili.com/video/{id}/且可选是否连带复制视频标题。下面从组件注册入手逐步还原其完整实现。组件注册元数据驱动的声明式定义与 Bilibili-Evolved 中绝大多数功能一致「BV 号转换」采用元数据声明 按需加载的组件化架构。入口文件 index.ts 中通过defineComponentMetadata完成注册export const component defineComponentMetadata({ name: bvidConvert, displayName: BV 号转换, options, entry: none, tags: [componentsTags.video, componentsTags.utils], widget: { component: () import(./BvidConvert.vue).then(m m.default), condition: hasVideo, }, urlInclude: videoAndBangumiUrls, })各字段含义与设计意图如下字段值作用namebvidConvert组件唯一标识也是设置存储的键名displayNameBV 号转换在设置面板与功能面板中显示的名称optionscopyWithTitle选项组件自定义选项详见下文「可配置项」entrynone无需在页面注入常驻逻辑一切行为由挂件承载tagsvideoutils组件分类标签用于设置面板的分类筛选widget懒加载BvidConvert.vue条件hasVideo以挂件形态存在仅当页面存在视频时显示urlIncludevideoAndBangumiUrls组件仅在视频 / 番剧 / 活动页等 URL 下激活其中tags字段引用的componentsTags.video与componentsTags.utils定义于 src/components/types.tsvideo标签中文名「视频」图标mdi-play-circle-outline与utils标签中文名「工具」图标mdi-rocket-launch-outline共同标识了该组件「服务于视频场景的实用工具」这一双重属性也使其在设置面板的分类页中可被两类标签同时检索到。激活范围videoAndBangumiUrlsurlInclude: videoAndBangumiUrls限定了组件的生效页面。该常量定义于 src/core/utils/urls.tsexport const videoUrls [//www.bilibili.com/video/, ...festivalUrls, ...mediaListUrls] export const bangumiUrls [//www.bilibili.com/bangumi/play/] export const videoAndBangumiUrls [...videoUrls, ...bangumiUrls]可以看出激活范围覆盖了三类页面常规视频页//www.bilibili.com/video/活动/节日专题页festivalUrls视频列表合集/分P 列表页mediaListUrls番剧播放页//www.bilibili.com/bangumi/play/。这解释了为何复制链接逻辑需要针对「参数类页面如 festival」和「番剧」做特判详见下文「链接构造」小节。可配置项copyWithTitle组件通过defineOptionsMetadata声明了一个选项const options defineOptionsMetadata({ copyWithTitle: { defaultValue: false, displayName: 复制链接时带上标题, }, })键名copyWithTitle默认值false显示名复制链接时带上标题其语义为开启后点击复制按钮时剪贴板内容会从「纯链接」变为「视频标题 空格 链接」方便直接粘贴到聊天、笔记等场景。选项类型通过OptionsOfMetadatatypeof options导出为BvidConvertOptions供视图组件通过getComponentSettingsBvidConvertOptions(bvidConvert)读取——注意这里读取时使用的键名必须与注册时的name一致const { options } getComponentSettingsBvidConvertOptions(bvidConvert)该选项在设置面板中呈现为标准的开关控件用户可在「BV 号转换」组件详情中调整修改即时生效。挂件渲染何时显示、显示什么组件以Widget挂件形态挂载于功能面板。其渲染条件与内容分别由index.ts中的widget.condition和 BvidConvert.vue 的模板决定。显示条件hasVideocondition: hasVideo,hasVideo定义于 src/core/spin-query.tsexport const hasVideo async () { if (!hasVideoPromiseCache) { hasVideoPromiseCache new Promise(resolve videoChange(() resolve(unsafeWindow.cid))) } const cid await hasVideoPromiseCache return Boolean(cid) }其原理是调用一次videoChange等待视频加载完成若最终拿到unsafeWindow.cid视频分P 的唯一 ID则判定为「存在视频」从而在功能面板中渲染本挂件。hasVideoPromiseCache做了 Promise 级缓存避免在挂件列表反复渲染时重复等待。界面结构AV 号与 BV 号两行展示BvidConvert.vue的模板结构如下div classbvid-convert div v-ifaid classbvid-convert-item {{ aid }} div classbvid-convert-item-copy title复制链接 clickcopyLink(aid) VIcon :size16 :iconaidCopied ? mdi-check : mdi-link / /div /div div v-ifbvid classbvid-convert-item {{ bvid }} div classbvid-convert-item-copy title复制链接 clickcopyLink(bvid) VIcon :size16 :iconbvidCopied ? mdi-check : mdi-link / /div /div /div每个 ID 一行bvid-convert-item行内右侧为复制按钮bvid-convert-item-copy按钮图标使用 VIcon 组件常态为mdi-link链接图标复制成功后在 1 秒内切换为mdi-check对勾图标作为成功反馈复制按钮的title提示为「复制链接」鼠标悬停可预览。从样式文件可以看出该挂件的视觉细节容器设置了圆角、内边距、细边框阴影与user-select: text允许用户直接框选复制文本并适配了深色模式body.dark 时使用--be-color-card-bg变量作为背景。数据来源videoChange 驱动的 ID 抓取组件在mounted时注册videoChange回调随视频切换实时刷新 IDasync mounted() { videoChange(async () { this.aid av${unsafeWindow.aid} this.bvid unsafeWindow.bvid const link (await select(.av-link,.bv-link,.bvid-link)) as HTMLElement if (link) { this.bvid link.innerHTML.trim() } }) }抓取策略分为两层直接读取全局变量unsafeWindow.aid/unsafeWindow.bvid是哔哩哔哩播放页暴露的全局数据aid前拼接av前缀后展示DOM 兜底修正通过select(.av-link,.bv-link,.bvid-link)在页面中查找 B 站渲染的 ID 链接元素若存在则以其innerHTML覆盖bvid值——这一层兜底可处理部分页面全局变量缺失或与页面显示不一致的情况。videoChange是 Bilibili-Evolved 核心的事件机制定义于 src/core/observer.ts它先通过matchCurrentPage(playerUrls)判断是否处于播放页再等待cid就绪随后通过MutationObserverallMutations监听 DOM 变化在检测到cid变化时向window派发videoChange自定义事件使回调在切换分P / 切换视频时都能被触发从而保证挂件展示的 ID 始终与当前播放内容一致。复制链接三种场景的 URL 构造复制是组件的核心交互。点击任意一行的复制按钮后调用copyLink(type)其完整流程为async copyLink(data: CopyIdType) { if (this[${data}Copied]) return const context { query: location.search, url: location.origin location.pathname, id: this[data], } const link linkProviders.map(p p(context)).filter(it it ! null)[0] if (options.copyWithTitle) { await navigator.clipboard.writeText(${getFriendlyTitle()} ${link}) } else { await navigator.clipboard.writeText(link) } this[${data}Copied] true setTimeout(() (this[${data}Copied] false), 1000) }要点如下防重复点击若该 ID 已处于「复制成功」状态aidCopied/bvidCopied为true则直接返回避免连续触发上下文信息context携带当前页面查询串query、页面地址url与目标 IDid供链接构造器决策链接生成依次执行linkProviders中的构造器取第一个非null结果写入剪贴板使用navigator.clipboard.writeText当copyWithTitle开启时通过getFriendlyTitle()获取页面友好标题并拼接在链接前getFriendlyTitle来自 src/core/utils/title.ts成功反馈置Copied标志并切换图标1 秒后复位。linkProviders按优先级定义了三种 URL 构造场景见 BvidConvert.vue1. 参数类页面如 festival 活动页({ id, query }) { if (copyIds.some(copyId query.includes(${copyId}))) { return https://www.bilibili.com/video/${id}/ } return null }当 URL 查询串中已含aid或bvid参数典型如 festival 专题页?bvidxxx时直接构造标准视频链接。之所以需要特判是因为此类页面的路径不在//www.bilibili.com/video/之下无法复用普通视频的逻辑。2. 番剧播放页({ id }) { if (bangumiUrls.some(u matchUrlPattern(u))) { return https://www.bilibili.com/video/${id}/ } return null }当当前页面匹配bangumiUrls//www.bilibili.com/bangumi/play/时同样返回标准视频链接——番剧分P 往往与普通视频共用 AV/BV 体系该构造器让番剧场景也能复制出可直达的链接。3. 普通视频页默认兜底({ id, query }) { const params new URLSearchParams(query) const newQuery new URLSearchParams() for (const key of [p, t]) { const value params.get(key) if (value) newQuery.set(key, value) } return https://www.bilibili.com/video/${id}/${ newQuery.size 0 ? ?${newQuery.toString()} : } }作为兜底逻辑它从当前查询串中透传p分P 序号与t播放进度秒数两个参数使复制出的链接能保留用户当前观看的分P 与进度位置无相关参数时不附加查询串。这一设计兼顾了「纯净链接」与「精确跳转」两种诉求。运行时数据流小结综合上述实现可将「BV 号转换」的完整数据流概括为页面加载后urlInclude判定当前 URL 是否在激活范围内功能面板渲染时评估hasVideo内部经videoChange等待cid通过后在面板中挂载BvidConvert.vue挂件挂件mounted后再次注册videoChange回调视频/分P 切换时刷新aidav前缀与bvid优先取全局变量必要时以.bv-link等 DOM 元素内容修正用户点击复制按钮linkProviders依据页面类型参数类页面 → 番剧 → 普通视频依次尝试构造https://www.bilibili.com/video/{id}/链接并按copyWithTitle选项决定是否附带getFriendlyTitle()标题剪贴板写入成功后按钮图标短暂切换为对勾以作反馈。总结一个小功能背后的组件化范式「BV 号转换」虽然只承担「展示 复制」两个简单职责但其实现完整展现了 Bilibili-Evolved 的组件化开发范式元数据注册defineComponentMetadata统一管理名称、分类、URL 激活范围与挂件声明选项系统defineOptionsMetadatagetComponentSettings让每个组件拥有独立的可配置项与持久化设置核心事件复用videoChange、hasVideo、select使组件无需关心底层 DOM 观测与视频状态轮询即可获得「随视频切换实时更新」的能力场景化兜底三层linkProviders用少量代码优雅覆盖了参数页、番剧与普通视频三类差异页面。对于希望在增强脚本中实现「页面信息展示 / 快捷复制」类功能的开发者本文所述的注册、条件渲染、数据监听与链接构造流程是一份可直接参考的最小完整实现示例。【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考