Skip to content
Merged

7.3.6 #650

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ npm run preview # 打开提供编译产物安装链接的本地预览网页

- `src/library/bili-api/` 中的 API 必须有详细的请求/响应类型定义
- 路径别名 `@/` 映射到 `src/`
- 代码中的 import 语句一律省略 TypeScript 文件扩展名(`.ts`、`.d.ts`)和目录的 `/index` 后缀
- Commit message 使用约定式提交格式

# 易踩坑点
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## [Unreleased]

## [7.3.6] - 2026-8-27

### 修复

- 修复粉丝勋章名单中同一个勋章重复出现的bug(B站接口有概率重复返回同一个勋章)

### 调整

- 优化【隐藏/显示控制面板】按钮样式,不占用B站原生元素空间;如果空间不足与B站活动组件发生重叠,按钮会显示在上方
- 直播任务板块部分日志优化

## [7.3.5] - 2026-8-26

### 修复
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "bilibili-live-tasks-helper",
"private": true,
"version": "7.3.5",
"version": "7.3.6",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
39 changes: 32 additions & 7 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,21 @@ const isShowPanel = uiStore.uiConfig.isShowPanel
// 太早显示会导致几个字悬浮在屏幕左上角的问题
uiStore.uiConfig.isShowPanel = false
// 显示/隐藏控制面板按钮
let button: HTMLButtonElement
let button: HTMLButtonElement | null = null
// 按钮的定位锚点(.normal-row-ctnr 的第一个子节点)
let buttonAnchor: HTMLElement | null = null
/**
* 更新播放器的大小、位置和滚动条位置
* 更新显示/隐藏控制面板按钮的位置
*/
function updatePosition() {
function updateButtonPosition() {
if (!button || !buttonAnchor) return
// 15 是按钮与左侧内容之间的间距
button.style.left = `${buttonAnchor.offsetLeft + buttonAnchor.offsetWidth + 15}px`
}
/**
* 同步播放器的大小、位置和窗口滚动条位置到 uiStore
*/
function syncLivePlayerRect() {
const rect: DOMRect = livePlayer!.getBoundingClientRect()

uiStore.livePlayerRect.top = rect.top
Expand All @@ -39,14 +49,17 @@ function updatePosition() {
*/
function buttonOnClick() {
uiStore.changeShowPanel()
button.innerText = uiStore.isShowPanelButtonText

if (button) {
button.innerText = uiStore.isShowPanelButtonText
}
}
// 节流,防止点击过快,减小渲染压力
const throttleButtonOnClick = _.throttle(buttonOnClick, 300)
// 播放器节点出现在最初的html中,可以直接获取
const livePlayer = dq('.player-section')
if (livePlayer) {
updatePosition()
syncLivePlayerRect()
// 节点 #player-ctnr 在初始 html 中出现
waitForElement(dq('#player-ctnr')!, '.header-info-ctnr .normal-row-ctnr', 10e3)
.then((normalRowCtnr) => {
Expand All @@ -63,6 +76,18 @@ if (livePlayer) {
logger.warn('.normal-row-ctnr 没有子节点', normalRowCtnr)
normalRowCtnr.appendChild(button)
}
// 记录按钮的定位锚点
buttonAnchor =
normalRowCtnr.firstElementChild instanceof HTMLElement
? normalRowCtnr.firstElementChild
: null
// 初始化按钮位置
updateButtonPosition()
// 锚点宽度变化时更新按钮位置
if (buttonAnchor) {
const buttonAnchorObserver = new ResizeObserver(() => updateButtonPosition())
buttonAnchorObserver.observe(buttonAnchor)
}
if (!isSelfTopFrame()) {
// 在特殊直播间,脚本所在的目标 frame 只占屏幕中间一块地方
// 如果焦点不在里面,快捷键会失效
Expand All @@ -80,10 +105,10 @@ if (livePlayer) {
.catch((e: Error) => logger.error(e))
// 监听页面缩放,调整控制面板大小
// 因为这个操作频率不高就不节流或防抖了
window.addEventListener('resize', () => updatePosition())
window.addEventListener('resize', () => syncLivePlayerRect())
// 监听 html 根节点和 body 节点
// 适配播放器网页模式
const observer = new MutationObserver(() => updatePosition())
const observer = new MutationObserver(() => syncLivePlayerRect())
observer.observe(document.body, { attributes: true })
observer.observe(document.documentElement, { attributes: true })

Expand Down
14 changes: 10 additions & 4 deletions src/assets/css/base.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/* 显示/隐藏控制面板按钮 */
/**
显示/隐藏控制面板按钮
按钮使用绝对定位,不参与 .normal-row-ctnr 的 flex 布局,避免挤占右侧活动组件的显示空间;
left 由 JS 根据锚点宽度动态设置
*/
.blth-btn {
position: absolute;
top: 50%;
z-index: 1003;
padding: 5px;
margin-left: 15px;
font-size: small;
line-height: 10px;
color: #fff;
Expand All @@ -10,16 +16,16 @@
border: none;
border-radius: 4px;
box-shadow: 0 0 2px #00000075;
transform: translateY(-50%);
}

.blth-btn:hover {
background-color: #1097cc;
}

.blth-btn:hover:active {
position: relative;
top: 1px;
background-color: #0e86b6;
transform: translateY(calc(-50% + 1px));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/library/bili-api/data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ declare namespace LiveData {

namespace GetWidgetBannerList {
interface Data {
/** 键为组件 id 的字符串形式,没有任何组件时可能为 null */
/** 键为组件 id 的字符串形式,没有任何组件时为 null */
list: Record<string, Banner> | null
room_id: number
/** 主播 uid */
Expand Down
17 changes: 9 additions & 8 deletions src/modules/dailyTasks/liveTasks/medalTasks/MedalModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ class MedalModule extends BaseModule {
canTryNextPage: currentPage < totalPage && !hasUnlightedMedal,
}
}
this.logger.warn(`BAPI.live.fansMedalPanel(${page}) 失败`, response.message)
this.logger.warn(`fansMedalPanel(${page}) 获取直播状态失败`, response.message)
} catch (error) {
this.logger.warn(`BAPI.live.fansMedalPanel(${page}) 出错`, error)
this.logger.warn(`fansMedalPanel(${page}) 获取直播状态出错`, error)
}
return { status: null, canTryNextPage: false }
}
Expand Down Expand Up @@ -159,9 +159,9 @@ class MedalModule extends BaseModule {
MedalModule.liveStatusSnapshots.set(roomid, { liveStatus, observedAt: tsm() })
return liveStatus
}
this.logger.warn(`BAPI.live.getInfoByRoom(${roomid}) 失败`, response.message)
this.logger.warn(`getInfoByRoom(${roomid}) 获取直播状态失败`, response.message)
} catch (error) {
this.logger.warn(`BAPI.live.getInfoByRoom(${roomid}) 出错`, error)
this.logger.warn(`getInfoByRoom(${roomid}) 获取直播状态出错`, error)
}

return null
Expand All @@ -175,9 +175,9 @@ class MedalModule extends BaseModule {
MedalModule.liveStatusSnapshots.set(roomid, { liveStatus, observedAt: tsm() })
return liveStatus
}
this.logger.warn(`BAPI.live.getRoomPlayInfo(${roomid}) 失败`, response.message)
this.logger.warn(`getRoomPlayInfo(${roomid}) 获取直播状态失败`, response.message)
} catch (error) {
this.logger.warn(`BAPI.live.getRoomPlayInfo(${roomid}) 出错`, error)
this.logger.warn(`getRoomPlayInfo(${roomid}) 获取直播状态出错`, error)
}

return null
Expand Down Expand Up @@ -595,14 +595,15 @@ class MedalModule extends BaseModule {
try {
const response = await BAPI.live.getActivatedMedalInfo(target_id)
this.logger.log(`BAPI.live.getActivatedMedalInfo(${target_id}) response`, response)

if (response.code === 0) {
return response.data
} else {
this.logger.error(`BAPI.live.getActivatedMedalInfo(${target_id}) 失败`, response.message)
this.logger.error(`获取粉丝勋章信息失败(主播uid:${target_id})`, response.message)
return null
}
} catch (error) {
this.logger.error(`BAPI.live.getActivatedMedalInfo(${target_id}) 出错`, error)
this.logger.error(`获取粉丝勋章信息出错(主播uid:${target_id})`, error)
return null
}
})
Expand Down
Loading