feat 添加取消收藏、收藏夹选择功能

This commit is contained in:
hanyixuanten
2026-07-03 22:16:57 +08:00
parent cdf2f16ce3
commit 5568e1c848
4 changed files with 223 additions and 4 deletions
+8
View File
@@ -7,6 +7,14 @@ export const BilibiliClientFavFolderMethods = {
return response.data.data;
},
// 获取用户所有收藏夹及目标视频在各收藏夹中的收藏状态
// 返回的每个 folder 对象中包含 fav_state 字段:0=未收藏, 1=已收藏
async getUserFavouriteFoldersWithVideoState(this: any, mid: string, aid: string): Promise<any> {
const url = `https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid=${mid}&type=2&rid=${aid}`;
const response = await this.getRequest(url);
return response.data.data;
},
// 获取目标收藏夹元数据
async getFavouriteFolderMetadata(this: any, mlid: string): Promise<any> {
const url = `https://api.bilibili.com/x/v3/fav/folder/info?media_id=${mlid}`;
+52
View File
@@ -38,4 +38,56 @@ export const BilibiliClientVideoActionMethods = {
return false;
}
},
// 取消收藏视频从默认收藏夹
async unstarVideoFromDefaultFavFolderByBVID(this: any, bvid: string): Promise<any> {
let defaultFolderID = 0;
const folders = await this.getUserFavouriteFolders(this.accountInfo.mid);
folders.list.forEach((folder: any) => {
if (folder.title === "默认收藏夹") {
defaultFolderID = folder.id;
}
});
if (!defaultFolderID) return false;
try {
const videoInfo = await this.getVideoInfoByBVID(bvid);
const aid = videoInfo.aid;
const url = `https://api.bilibili.com/x/v3/fav/resource/deal`;
const data = `rid=${aid}&csrf=${this.biliJct}&type=2&add_media_ids=&del_media_ids=${defaultFolderID}`;
const response = await this.postRequest(url, data, "application/x-www-form-urlencoded");
return response.data.code;
} catch (error) {
global.logger.error("Error unstarring video: ", error);
return false;
}
},
// 收藏视频至指定收藏夹(支持多个)
async starVideoToFavFolders(this: any, aid: string, folderIds: string[]): Promise<any> {
try {
const add_media_ids = folderIds.join(',');
const url = `https://api.bilibili.com/x/v3/fav/resource/deal`;
const data = `rid=${aid}&csrf=${this.biliJct}&type=2&add_media_ids=${add_media_ids}&del_media_ids=`;
const response = await this.postRequest(url, data, "application/x-www-form-urlencoded");
return response.data.code;
} catch (error) {
global.logger.error("Error starring video to folders: ", error);
return false;
}
},
// 从指定收藏夹取消收藏视频(支持多个)
async unstarVideoFromFavFolders(this: any, aid: string, folderIds: string[]): Promise<any> {
try {
const del_media_ids = folderIds.join(',');
const url = `https://api.bilibili.com/x/v3/fav/resource/deal`;
const data = `rid=${aid}&csrf=${this.biliJct}&type=2&add_media_ids=&del_media_ids=${del_media_ids}`;
const response = await this.postRequest(url, data, "application/x-www-form-urlencoded");
return response.data.code;
} catch (error) {
global.logger.error("Error unstarring video from folders: ", error);
return false;
}
},
}
@@ -52,4 +52,73 @@
.vidtoolimg {
width: 62px;
}
.fav-folder-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
flex-direction: column;
justify-content: center;
align-items: center;
}
.fav-folder-picker {
width: 340px;
height: 380px;
background-color: #2a2a2a;
border-radius: 16px;
flex-direction: column;
align-items: center;
padding: 20px;
}
.fav-folder-picker-title {
font-size: 22px;
font-weight: 700;
color: #ffffff;
margin-bottom: 15px;
}
.fav-folder-list {
width: 100%;
height: 260px;
flex-direction: column;
}
.fav-folder-item {
flex-direction: row;
align-items: center;
padding: 10px 8px;
margin-bottom: 4px;
border-radius: 8px;
background-color: #3a3a3a;
}
.fav-folder-item-selected {
background-color: #4a6fa5;
}
.fav-folder-checkmark {
font-size: 20px;
color: #ffffff;
margin-right: 10px;
width: 28px;
text-align: center;
}
.fav-folder-name {
font-size: 18px;
color: #ffffff;
flex: 1;
}
.fav-folder-buttons {
flex-direction: row;
justify-content: space-between;
width: 100%;
margin-top: 15px;
}
+94 -4
View File
@@ -54,6 +54,22 @@
</scroll>
<full-screen-input style="position: absolute" if="{{replymode}}" @send="SendReply"
@exit="ExitInput"></full-screen-input>
<div class="fav-folder-overlay" if="{{favFolderPickerVisible}}">
<div class="fav-folder-picker">
<text class="fav-folder-picker-title">选择收藏夹</text>
<scroll scroll-y="true" class="fav-folder-list">
<div class="fav-folder-item {{folder.selected ? 'fav-folder-item-selected' : ''}}"
for="folder in favFolders" @click="ToggleFolder(folder.id)">
<text class="fav-folder-checkmark">{{folder.selected ? '✓' : '○'}}</text>
<text class="fav-folder-name">{{folder.title}}</text>
</div>
</scroll>
<div class="fav-folder-buttons">
<default-button text="取消" @click="HideFavFolderPicker"></default-button>
<default-button text="确认" @click="ConfirmAddToFav"></default-button>
</div>
</div>
</div>
</div>
</template>
@@ -77,7 +93,9 @@ export default {
starsrc: "/common/vidtool_star.png",
replymode: false,
renderingCover: false,
scrclass: ""
scrclass: "",
favFolderPickerVisible: false,
favFolders: []
},
computed: {
stat_view() {
@@ -220,11 +238,83 @@ export default {
})
},
async AddToFav() {
const result = await global.biliclient.starVideoToDefaultFavFolderByBVID(this.bvid)
const message = result ? "收藏失败,请重试,或重新登录后再试" : "收藏成功"
prompt.showToast({message})
if (this.stared) {
// 已收藏:从所有包含此视频的收藏夹中删除
await this.ConfirmUnstarAll()
} else {
// 未收藏:弹出收藏夹选择窗口
await this.ShowFavFolderPicker()
}
},
async ShowFavFolderPicker() {
try {
var self = this
var data = await global.biliclient.getUserFavouriteFoldersWithVideoState(
global.biliclient.accountInfo.mid,
this.vid.aid
)
var list = data.list || []
this.favFolders = list.map(function(folder) {
return {
id: folder.id,
title: folder.title,
selected: folder.fav_state === 1
}
})
this.favFolderPickerVisible = true
} catch (e) {
global.logger.error("获取收藏夹列表失败: ", e)
prompt.showToast({message: "获取收藏夹列表失败,请重试"})
}
},
HideFavFolderPicker() {
this.favFolderPickerVisible = false
},
ToggleFolder(folderId) {
this.favFolders = this.favFolders.map(function(f) {
if (f.id === folderId) {
return Object.assign({}, f, { selected: !f.selected })
}
return f
})
},
async ConfirmAddToFav() {
var selectedIds = this.favFolders
.filter(function(f) { return f.selected })
.map(function(f) { return f.id })
this.favFolderPickerVisible = false
if (selectedIds.length === 0) {
prompt.showToast({message: "未选择任何收藏夹"})
return
}
var result = await global.biliclient.starVideoToFavFolders(this.vid.aid, selectedIds)
var message = result === 0 ? "收藏成功" : "收藏失败,请重试,或重新登录后再试"
prompt.showToast({message: message})
this.UpdateVideoToolbarStatus()
},
async ConfirmUnstarAll() {
try {
var data = await global.biliclient.getUserFavouriteFoldersWithVideoState(
global.biliclient.accountInfo.mid,
this.vid.aid
)
var list = data.list || []
var staredFolderIds = list
.filter(function(f) { return f.fav_state === 1 })
.map(function(f) { return f.id })
if (staredFolderIds.length === 0) {
prompt.showToast({message: "该视频未被收藏"})
return
}
var result = await global.biliclient.unstarVideoFromFavFolders(this.vid.aid, staredFolderIds)
var message = result === 0 ? "取消收藏成功" : "取消收藏失败,请重试,或重新登录后再试"
prompt.showToast({message: message})
this.UpdateVideoToolbarStatus()
} catch (e) {
global.logger.error("取消收藏失败: ", e)
prompt.showToast({message: "取消收藏失败,请重试"})
}
},
async GenBlur(evt) {
// 该Feature在现在任何设备上运行都会卡死,故注释
/*