mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Split components into separate files
This commit is contained in:
parent
4d5e54e50d
commit
bea49cc786
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -30,9 +30,21 @@
|
|||||||
"custom-control-background.min.js": "2A439B045A51D24F5115DD25995ED37E3D0371A074199FE6C727F2235F39C4D9",
|
"custom-control-background.min.js": "2A439B045A51D24F5115DD25995ED37E3D0371A074199FE6C727F2235F39C4D9",
|
||||||
"custom-navbar.min.css": "43732294A2B6C4ABCA27100A52A2FA9DAB2F37953D3B2846A11AF0EE9265B46D",
|
"custom-navbar.min.css": "43732294A2B6C4ABCA27100A52A2FA9DAB2F37953D3B2846A11AF0EE9265B46D",
|
||||||
"custom-navbar.min.html": "8A5332791C9693A571F7B885D6367616F519054CACEDA2DDA147735638EDEE15",
|
"custom-navbar.min.html": "8A5332791C9693A571F7B885D6367616F519054CACEDA2DDA147735638EDEE15",
|
||||||
"custom-navbar.min.js": "5467CA8B5A15CEB26747A3C109F9C9BC880BE4AA77639E5839C8B6B6E9023CD4",
|
"custom-navbar.min.js": "570243FFB975DE633CF78EECD20755DC7B22BE011C9F5FE8C453AC7D299D1168",
|
||||||
"custom-navbar-component.min.js": "82B271CA295D44A8CC82008FBA8D7956C5ECF98E8CC79028CDB9AA8210ED169E",
|
"custom-navbar-activities.min.js": "56759EC7004186C0BADF9903217191C9E6035437CADF5F640DB8CBD8C5171201",
|
||||||
|
"custom-navbar-blank.min.js": "DC2B75D5760EECD3A257785FDFBB7E5DEBF61CD9083C68DD5BCE468B093F54F3",
|
||||||
|
"custom-navbar-category.min.js": "4CF38ACE1D0501217266D1E35DFCBF9D5C1D9A3838C54D53C614878BB8CF55E2",
|
||||||
|
"custom-navbar-component.min.js": "811D5A1B00158587891496A9D371177CA676225E2CE778E5CCA340586F5C69E6",
|
||||||
|
"custom-navbar-iframe.min.js": "C4EE469EC09655F9FF535ACBBD2A5F7C332DA2081936F8F485F5FB015EBD794B",
|
||||||
|
"custom-navbar-logo.min.js": "236CCC887A3917A6D4840889B7380B648197765B8CDA27CB233F3F1E3215F7BB",
|
||||||
|
"custom-navbar-messages.min.js": "D7B315A4D8FD9E2EF9C1E40C1F3CA7EC18C5A87AC7A9410049061A0D851868DE",
|
||||||
|
"custom-navbar-search-box.min.js": "F91CB1678AE6E353148134A16184BDC67C8310099000986451F3668E7F505345",
|
||||||
"custom-navbar-settings.min.js": "BF251CA22EF6F8B681C70F9CC5C9DC3A31D6AAE3968CA3990722A0191B06AB13",
|
"custom-navbar-settings.min.js": "BF251CA22EF6F8B681C70F9CC5C9DC3A31D6AAE3968CA3990722A0191B06AB13",
|
||||||
|
"custom-navbar-simple-link.min.js": "0960197FB525733551435B07D7B024272C21BDD2D8B4F47027046FCE7B3468C5",
|
||||||
|
"custom-navbar-subscriptions.min.js": "40F7ACEB501462A72D6BC15D1814DFD8A75B9FA6867748F362593CB00260C51E",
|
||||||
|
"custom-navbar-upload.min.js": "0CDEEA46DCF0D6187C86BB12DE8CD36737116EF171AA1F63AB20C5DC7549C976",
|
||||||
|
"custom-navbar-user-info.min.js": "F0C8D9FC280BA0A69746EC36079FA97AD9F0B69EB7D8FB56C6ED815C46791321",
|
||||||
|
"custom-navbar-video-list.min.js": "08D6713144E910C1303CB610A5890A5663B92BE82630BDA3C8E6299FB4A429E2",
|
||||||
"custom-navbar-watchlater-list.min.js": "1C64C6829708C9A0C14499586A27B7E6EE64686205F4C91F6E194161C085C5A3",
|
"custom-navbar-watchlater-list.min.js": "1C64C6829708C9A0C14499586A27B7E6EE64686205F4C91F6E194161C085C5A3",
|
||||||
"danmaku-converter.min.js": "FDAB4DB2E3C79730A39CDA7C5FD193693621FED206C6549E9B8F13778080CC12",
|
"danmaku-converter.min.js": "FDAB4DB2E3C79730A39CDA7C5FD193693621FED206C6549E9B8F13778080CC12",
|
||||||
"dark.min.css": "BE3EEA67383A7382C6D470A0DF48798069D1F10842653CE5B0364831B64B07C9",
|
"dark.min.css": "BE3EEA67383A7382C6D470A0DF48798069D1F10842653CE5B0364831B64B07C9",
|
||||||
|
|||||||
BIN
min/bundle.zip
BIN
min/bundle.zip
Binary file not shown.
1
min/custom-navbar-activities.min.js
vendored
Normal file
1
min/custom-navbar-activities.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
min/custom-navbar-blank.min.js
vendored
Normal file
1
min/custom-navbar-blank.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(t,e)=>{const{NavbarComponent:n}=e.import("custom-navbar-component");class r extends n{constructor(t){super();this.number=t;this.flex="1 0 auto";this.disabled=true}get name(){return"blank"+this.number}}return{export:{Blank:r}}}})();
|
||||||
1
min/custom-navbar-category.min.js
vendored
Normal file
1
min/custom-navbar-category.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
min/custom-navbar-component.min.js
vendored
2
min/custom-navbar-component.min.js
vendored
@ -1 +1 @@
|
|||||||
(()=>{return(t,e)=>{class n{constructor(e="",n="",s="0 0 auto",a=false,i=false,r=null,o=null,u=null,l=0,c=t.touchNavBar,h=false){this.html=e;this.popupHtml=n;this.flex=s;this.disabled=a;this.requestedPopup=i;this.initialPopup=r;this.onPopup=o;this.href=u;this.notifyCount=l;this.touch=c;this.active=h;this.noPadding=false}get name(){return"blank1"}get order(){return t.customNavbarOrder[this.name]}get hidden(){return t.customNavbarHidden.includes(this.name)}async setNotifyCount(t){const e=await SpinQuery.select(`.custom-navbar li[data-name='${this.name}'] .notify-count`);if(!e||!t){e.innerHTML="";return}e.innerHTML=t.toString()}async setNotifyStyle(t){const e=await SpinQuery.select(`.custom-navbar li[data-name='${this.name}'] .notify-count`);if(!e){return}const n={1:"number",2:"dot",3:"hidden"};e.classList.remove(...Object.values(n));e.classList.add(n[t])}}return{export:{NavbarComponent:n}}}})();
|
(()=>{return(t,e)=>{class n{constructor(e="",n="",s="0 0 auto",a=false,i=false,r=null,o=null,u=null,l=0,c=t.touchNavBar,h=false){this.html=e;this.popupHtml=n;this.flex=s;this.disabled=a;this.requestedPopup=i;this.initialPopup=r;this.onPopup=o;this.href=u;this.notifyCount=l;this.touch=c;this.active=h;this.noPadding=false;this.transparent=false}get name(){return"blank1"}get order(){return t.customNavbarOrder[this.name]}get hidden(){return t.customNavbarHidden.includes(this.name)}async setNotifyCount(t){const e=await SpinQuery.select(`.custom-navbar li[data-name='${this.name}'] .notify-count`);if(!e||!t){e.innerHTML="";return}e.innerHTML=t.toString()}async setNotifyStyle(t){const e=await SpinQuery.select(`.custom-navbar li[data-name='${this.name}'] .notify-count`);if(!e){return}const n={1:"number",2:"dot",3:"hidden"};e.classList.remove(...Object.values(n));e.classList.add(n[t])}}return{export:{NavbarComponent:n}}}})();
|
||||||
1
min/custom-navbar-iframe.min.js
vendored
Normal file
1
min/custom-navbar-iframe.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(t,e)=>{const{NavbarComponent:r}=e.import("custom-navbar-component");class a extends r{constructor(t,e,r){super();const{src:a,width:s,height:i,lazy:n,iframeName:h}=r;this.iframeName=h;this.html=t;this.href=e;this.popupHtml=`\n<iframe src='${a}' frameborder='0' width='${s}' height='${i}'></iframe>\n`;this.noPadding=true;this.requestedPopup=n?false:true;this.touch=false;this.transparent=true}get name(){return this.iframeName+"Iframe"}}return{export:{Iframe:a}}}})();
|
||||||
1
min/custom-navbar-logo.min.js
vendored
Normal file
1
min/custom-navbar-logo.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(t,o)=>{const{NavbarComponent:s}=o.import("custom-navbar-component");class e extends s{constructor(){super();this.href=`https://www.bilibili.com/`;this.touch=false;addSettingsListener("customNavbarSeasonLogo",()=>this.getLogo(),true)}async getLogo(){if(t.customNavbarSeasonLogo){const t=await Ajax.getJson("https://api.bilibili.com/x/web-show/res/locs?pf=0&ids=142");if(t.code===0){this.html=`<img height="38" src="${t.data[142][0].litpic.replace("http:","https:")}">`;return}}this.html=`<i class="custom-navbar-iconfont custom-navbar-icon-logo"></i>`}get name(){return"logo"}}return{export:{Logo:e}}}})();
|
||||||
1
min/custom-navbar-messages.min.js
vendored
Normal file
1
min/custom-navbar-messages.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(t,e)=>{const{NavbarComponent:a}=e.import("custom-navbar-component");class i extends a{constructor(){super();this.href="https://message.bilibili.com/";this.html="消息";this.popupHtml=`\n<ul id="message-list">\n<li><a data-name="reply" target="_blank" href="https://message.bilibili.com/#/reply">回复我的</a></li>\n<li><a data-name="at" target="_blank" href="https://message.bilibili.com/#/at">@我的</a></li>\n<li><a data-name="like" target="_blank" href="https://message.bilibili.com/#/love">收到的赞</a></li>\n<li><a data-name="user_msg" target="_blank" href="https://message.bilibili.com/#/whisper">我的消息</a></li>\n<li><a data-name="sys_msg" target="_blank" href="https://message.bilibili.com/#/system">系统通知</a></li>\n</ul>\n`;this.requestedPopup=true;this.active=document.URL.startsWith("https://message.bilibili.com/");this.fetchSettings().then(t=>{if(t){this.init()}})}get name(){return"messages"}async fetchSettings(){const t=await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/link_setting/v1/link_setting/get?msg_notify=1`);if(t.code!==0){return}await this.setNotifyStyle(t.data.msg_notify);return t.data.msg_notify!==3}async init(){const t=await Ajax.getJsonWithCredentials(`https://api.bilibili.com/x/msgfeed/unread`);const e=await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/session_svr/v1/session_svr/single_unread`);const a=await SpinQuery.select("#message-list");const i=[...a.querySelectorAll("a[data-name]")];const s=i.map(t=>t.getAttribute("data-name"));if(t.code!==0||e.code!==0){return}t.data["user_msg"]=e.data.unfollow_unread+e.data.follow_unread;let n=s.reduce((e,a)=>e+t.data[a],0);if(!n){return}await this.setNotifyCount(n);s.forEach((e,a)=>{const s=t.data[e];if(s>0){i[a].setAttribute("data-count",s.toString())}else{i[a].removeAttribute("data-count")}});i.forEach(t=>{t.addEventListener("click",()=>{const e=parseInt(t.getAttribute("data-count"));t.removeAttribute("data-count");n-=e;this.setNotifyCount(n)})})}}return{export:{Messages:i}}}})();
|
||||||
1
min/custom-navbar-search-box.min.js
vendored
Normal file
1
min/custom-navbar-search-box.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(e,t)=>{const{NavbarComponent:s}=t.import("custom-navbar-component");class i extends s{constructor(){super();this.disabled=true;this.html=`\n<form id="custom-navbar-search" autocomplete="off" target="_blank" method="get" action="https://search.bilibili.com/all">\n<input type="text" placeholder="搜索" name="keyword">\n<input type="hidden" name="from_source" value="banner_search">\n<a style="display: none" target="_blank" class="recommended-target"></a>\n<button type="submit" title="搜索" tabindex="-1">\n<svg style="width:22px;height:22px" viewBox="0 0 24 24">\n<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />\n</svg>\n</button>\n</form>\n<div class="popup search-list" :class="{empty: items.length === 0}">\n<div class="search-list-item" tabindex="0" v-for="(item, index) of items" v-html="item.html" :title="isHistory ? item.html : ''" @keydown.enter="submit(item.value)" @click.self="submit(item.value)" @keydown.shift.delete="deleteItem(item, index)" @keydown.down.prevent="nextItem(index)" @keydown.up.prevent="previousItem(index)"></div>\n<div tabindex="0" v-if="items.length > 0 && isHistory" class="search-list-item clear-history" @click="clearSearchHistory()" @keydown.enter="clearSearchHistory()" @keydown.down.prevent="nextItem(items.length)" @keydown.up.prevent="previousItem(items.length)"><i class="mdi mdi-18px mdi-delete-sweep"></i>清除搜索历史</div>\n</div>\n`;this.init()}async init(){const t=await SpinQuery.select("#custom-navbar-search");const s=t.querySelector("input[name='keyword']");t.addEventListener("submit",i=>{if(s.value===""){if(!e.hideTopSearch){t.querySelector(".recommended-target").click()}i.preventDefault();return false}if(/^av[\d]+$/.test(s.value)){window.open(`https://www.bilibili.com/${s.value}`);i.preventDefault();return false}const a=e.searchHistory.find(e=>e.keyword===s.value);if(a){a.count++;a.date=(new Date).toJSON();console.log(a)}else{e.searchHistory.unshift({count:1,keyword:s.value,date:(new Date).toJSON()});console.log({count:1,keyword:s.value,date:(new Date).toJSON()})}e.searchHistory=e.searchHistory.slice(0,10);return true});if(!e.hideTopSearch){const e=await Ajax.getJson("https://api.bilibili.com/x/web-interface/search/default");if(e.code===0){s.setAttribute("placeholder",e.data.show_name);let i;if(e.data.url!==""){i=e.data.url}else if(e.data.name.startsWith("av")){i=`https://www.bilibili.com/${e.data.name}`}else{i=`https://search.bilibili.com/all?keyword=${e.data.name}`}t.querySelector(".recommended-target").setAttribute("href",i)}else{console.error("[自定义顶栏] 获取搜索推荐词失败")}}const i=new Vue({el:dq(".popup.search-list"),data:{items:[],isHistory:true},methods:{submit(e){s.value=e;t.submit();raiseEvent(t,"submit")},nextItem(e){const t=dq(`.custom-navbar .search-list-item:nth-child(${e+2})`);if(t){t.focus()}},previousItem(e){const t=dq(`.custom-navbar .search-list-item:nth-child(${e})`);if(t){t.focus()}else{s.focus();return}},deleteItem(t,s){e.searchHistory.splice(e.searchHistory.findIndex(e=>e.keyword===t.value),1);e.searchHistory=e.searchHistory;this.items.splice(s,1)},clearSearchHistory(){e.searchHistory=[];this.items=[]}}});let a="";const n=async()=>{const t=s.value;i.isHistory=t==="";if(i.isHistory){i.items=e.searchHistory.sort((e,t)=>{const s=e.date?new Date(e.date):new Date(0);const i=t.date?new Date(t.date):new Date(0);return Number(i)-Number(s)}).map(e=>{return{value:e.keyword,html:e.keyword}}).slice(0,10)}else{const e=`https://s.search.bilibili.com/main/suggest?func=suggest&suggest_type=accurate&sub_type=tag&main_ver=v1&highlight=&userid=${getUID()}&bangumi_acc_num=1&special_acc_num=1&topic_acc_num=1&upuser_acc_num=3&tag_num=10&special_num=10&bangumi_num=10&upuser_num=3&term=${t}`;a=e;const s=await Ajax.getJson(e);if(s.code!==0||a!==e){return}const n=s.result.tag;if(n===undefined){i.items=[];return}i.items=n.map(e=>{return{value:e.value,html:e.name.replace(/suggest_high_light/g,"suggest-highlight")}})}};n();const r=_.debounce(n,200);let o=false;s.addEventListener("compositionstart",()=>o=true);s.addEventListener("compositionend",()=>{o=false;raiseEvent(s,"input")});s.addEventListener("input",()=>{if(!o){r()}});s.addEventListener("keydown",e=>{if(e.key==="ArrowDown"&&i.items.length>0){e.preventDefault();dq(".custom-navbar .search-list-item:first-child").focus()}})}get name(){return"search"}}return{export:{SearchBox:i}}}})();
|
||||||
1
min/custom-navbar-simple-link.min.js
vendored
Normal file
1
min/custom-navbar-simple-link.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(t,e)=>{const{NavbarComponent:n}=e.import("custom-navbar-component");class s extends n{constructor(t,e,n){super();this.linkName=n;this.html=t;this.href=e;this.touch=false;this.active=document.URL.startsWith(e)}get name(){return this.linkName+"Link"}}return{export:{SimpleLink:s}}}})();
|
||||||
1
min/custom-navbar-subscriptions.min.js
vendored
Normal file
1
min/custom-navbar-subscriptions.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(i,s)=>{const{NavbarComponent:a}=s.import("custom-navbar-component");class t extends a{constructor(){super();this.noPadding=true;const i=getUID();this.href=`https://space.bilibili.com/${i}/bangumi`;this.html="订阅";this.active=[`https://space.bilibili.com/${i}/bangumi`,`https://space.bilibili.com/${i}/cinema`,`https://space.bilibili.com/${i}/subs`].includes(document.URL.replace(/\?.*$/,""));this.popupHtml=`\n<div class="subscriptions">\n<ul class="subscriptions-tabs">\n<li class="tab" :class="{selected: bangumi}" @click="bangumi = true">追番</li>\n<li class="tab" :class="{selected: !bangumi}" @click="bangumi = false">追剧</li>\n<div class="tab-placeholder"></div>\n<a class="view-all" target="_blank" :href="'https://space.bilibili.com/${i}/' + (bangumi ? 'bangumi' : 'cinema')">\n 查看更多\n<i class="mdi mdi-dots-horizontal"></i>\n</a>\n</ul>\n<div class="content">\n<transition name="subscriptions-content" mode="out-in">\n<bangumi-subscriptions v-if="bangumi" type="bangumi" :key="'bangumi'"></bangumi-subscriptions>\n<bangumi-subscriptions v-else type="cinema" :key="'cinema'"></bangumi-subscriptions>\n</transition>\n</div>\n</div>`;this.initialPopup=(()=>{this.init()})}async init(){new Vue({el:await SpinQuery.select(".custom-navbar .subscriptions"),data:{bangumi:true},components:{"bangumi-subscriptions":{props:["type"],components:{"dpi-img":()=>s.importAsync("dpi-img.vue")},template:`\n<div class="bangumi-subscriptions" :class="{center: loading || !loading && cards.length === 0}">\n<div v-if="loading" class="loading">\n<i class="mdi mdi-18px mdi-loading mdi-spin"></i>\n 加载中...\n</div>\n<div v-if="!loading && cards.length === 0" class="empty">空空如也哦 = ̄ω ̄=</div>\n<a v-if="!loading" v-for="card of cards" :key="card.id" :href="card.playUrl" target="_blank" class="bangumi-subscriptions-card">\n<dpi-img class="cover" :src="card.coverUrl" :size="{height: 64}"></dpi-img>\n<div class="card-info">\n<h1 class="title" :title="card.title">{{card.title}}</h1>\n<div class="progress-row">\n<div v-if="card.progress" class="progress" :title="card.progress + ' | ' + card.latest">{{card.progress}} | {{card.latest}}</div>\n<div v-else class="progress" :title="card.latest">{{card.latest}}</div>\n<a class="info" :href="card.mediaUrl" target="_blank" title="详细信息">\n<i class="mdi mdi-information-outline"></i>\n</a>\n</div>\n</div>\n</a>\n</div>\n`,data(){return{loading:true,cards:[]}},async mounted(){try{const i=await Ajax.getJsonWithCredentials(`https://api.bilibili.com/x/space/bangumi/follow/list?type=${this.type!=="bangumi"?"2":"1"}&pn=1&ps=16&vmid=${getUID()}`);if(i.code!==0){logError(`加载订阅信息失败: ${i.message}`);return}this.cards=i.data.list.map(i=>{return{title:i.title,coverUrl:i.square_cover.replace("http:","https:"),latest:i.new_ep.index_show,progress:i.progress,id:i.season_id,playUrl:`https://www.bilibili.com/bangumi/play/ss${i.season_id}`,mediaUrl:`https://www.bilibili.com/bangumi/media/md${i.media_id}`}})}finally{this.loading=false}}}}})}get name(){return"bangumi"}}return{export:{Subscriptions:t}}}})();
|
||||||
1
min/custom-navbar-upload.min.js
vendored
Normal file
1
min/custom-navbar-upload.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(i,t)=>{const{NavbarComponent:e}=t.import("custom-navbar-component");class a extends e{constructor(){super();this.href="https://member.bilibili.com/v2#/upload/video/frame";this.html=`\n<svg style="width:16px;height:16px;padding:3px;box-sizing:content-box;" viewBox="0 0 785 886">\n<path d="M582,374L582,566C582,585.333 576.167,600.833 564.5,612.5C552.833,624.167 537.333,630 518,630L262,630C242.667,630 227.167,624.167 215.5,612.5C203.833,600.833 198,585.333 198,566L198,374L32,374C22,374 14.1667,371.167 8.5,365.5C2.83333,359.833 0,352 0,342C0,338.667 1.16666,334.5 3.5,329.5C5.83333,324.5 8.66666,320 12,316L371,9C377.667,3.00006 385.167,6.10352e-005 393.5,0C401.833,6.10352e-005 409.333,3.00006 416,9L774,316C780,322.667 783.333,330.167 784,338.5C784.667,346.833 783.333,354.333 780,361L764,370C760,372.667 754.667,374 748,374ZM70,758L710,758C729.333,758 744.833,763.833 756.5,775.5C768.167,787.167 774,802.667 774,822C774,841.333 768.167,856.833 756.5,868.5C744.833,880.167 729.333,886 710,886L70,886C50.6667,886 35.1667,880.167 23.5,868.5C11.8333,856.833 6,841.333 6,822C6,802.667 11.8333,787.167 23.5,775.5C35.1667,763.833 50.6667,758 70,758Z" />\n</svg>\n<div id="upload-button">投稿</div>`;this.popupHtml=`\n<ul id="upload-actions">\n<li><a target="_blank" href="https://member.bilibili.com/v2#/upload/text/apply">专栏投稿</a></li>\n<li><a target="_blank" href="https://member.bilibili.com/v2#/upload/audio/">音频投稿</a></li>\n<li><a target="_blank" href="https://member.bilibili.com/v2#/upload/video/frame">视频投稿</a></li>\n<li><a target="_blank" href="https://member.bilibili.com/v2#/upload-manager/article">投稿管理</a></li>\n<li><a target="_blank" href="https://member.bilibili.com/v2#/home">创作中心</a></li>\n</ul>\n`}get name(){return"upload"}}return{export:{Upload:a}}}})();
|
||||||
1
min/custom-navbar-user-info.min.js
vendored
Normal file
1
min/custom-navbar-user-info.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
min/custom-navbar-video-list.min.js
vendored
Normal file
1
min/custom-navbar-video-list.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{return(t,i)=>{const{NavbarComponent:s}=i.import("custom-navbar-component");class e extends s{constructor({mainUrl:t,name:i,apiUrl:s,listName:e,listMap:a}){super();this.href=t;this.listName=e;this.html=i;this.noPadding=true;this.requestedPopup=false;this.popupHtml=`\n<ol class="video-list ${e}">\n<li class="loading">加载中...</li>\n</ol>\n`;this.initialPopup=(async()=>{if(!a){return}const l=await SpinQuery.select(`.video-list.${e}`);if(l===null){return}const r=await Ajax.getJsonWithCredentials(s);let n="";if(r.code!==0){logError(`加载${i}信息失败. 错误码: ${r.code} ${r.message}`)}else{n=a(r).join("")}l.insertAdjacentHTML("beforeend",n+`\n<li class="more"><a target="_blank" href="${t}">查看更多</a></li>\n`);l.classList.add("loaded")})}get name(){return this.listName+"List"}}class a extends e{constructor(){super({name:"收藏",mainUrl:`https://space.bilibili.com/${getUID()}/favlist`,apiUrl:"https://api.bilibili.com/medialist/gateway/coll/resource/recent",listName:"favorites",listMap:t=>{if(!t.data||t.data.length===0){return[`<li class="loading empty">空空如也哦 = ̄ω ̄=</li>`]}return t.data.map(t=>{return`\n<li>\n<a target="_blank" href="https://www.bilibili.com/video/av${t.id}">${t.title}</a>\n</li>`})}});this.active=document.URL.replace(/\?.*$/,"")===`https://space.bilibili.com/${getUID()}/favlist`}}class l extends e{constructor(){super({name:"历史",mainUrl:"https://www.bilibili.com/account/history",apiUrl:"https://api.bilibili.com/x/v2/history?pn=1&ps=6",listName:"history",listMap:t=>{if(!t.data||t.data.length===0){return[`<li class="loading empty">空空如也哦 = ̄ω ̄=</li>`]}return t.data.map(t=>{let i=[];let s="";const e=t.page?t.page.page:1;let a=t.progress>=0?t.progress/t.duration:1;if(isNaN(a)){a=0}if(e!==1){i.push(`p=${e}`);s+=`看到第${e}话`}if(t.progress>0&&t.progress<t.duration){i.push(`t=${t.progress}`);s+=` ${Math.floor(a*100)}%`}else if(t.progress===0){s+=` 刚开始看`}else{s+=" 100%"}return`\n<li class="history-item">\n<a target="_blank" href="https://www.bilibili.com/video/av${t.aid}?${i.join("&")}">\n<span class="title">${t.title}</span>\n<span class="description">${s}</span>\n<div class="progress background">\n<div class="progress foreground" style="--progress: ${a*100}%"></div>\n</div>\n</a>\n</li>`})}});this.active=document.URL.replace(/\?.*$/,"")==="https://www.bilibili.com/account/history"}}return{export:{FavoritesList:a,HistoryList:l}}}})();
|
||||||
2
min/custom-navbar.min.js
vendored
2
min/custom-navbar.min.js
vendored
File diff suppressed because one or more lines are too long
438
src/style/custom-navbar/activities/custom-navbar-activities.ts
Normal file
438
src/style/custom-navbar/activities/custom-navbar-activities.ts
Normal file
@ -0,0 +1,438 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
let componentUpdate = async () => { }
|
||||||
|
let tabUpdate = async () => { }
|
||||||
|
let latestID: string
|
||||||
|
interface ActivityTabComponentConfig {
|
||||||
|
dataObject: {}
|
||||||
|
apiUrl: string
|
||||||
|
name: string
|
||||||
|
handleJson: (json: any) => void
|
||||||
|
template: string
|
||||||
|
}
|
||||||
|
interface ActivityTab {
|
||||||
|
name: string
|
||||||
|
moreUrl: string
|
||||||
|
}
|
||||||
|
const getActivityTabComponent = ({ dataObject, apiUrl, name, handleJson, template }: ActivityTabComponentConfig) => {
|
||||||
|
return {
|
||||||
|
template,
|
||||||
|
components: {
|
||||||
|
'dpi-img': () => import('../dpi-img.vue'),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleJson,
|
||||||
|
async fetchData(silent = false) {
|
||||||
|
try {
|
||||||
|
const json = await Ajax.getJsonWithCredentials(apiUrl)
|
||||||
|
if (json.code !== 0) {
|
||||||
|
throw new Error(json.message)
|
||||||
|
}
|
||||||
|
await this.handleJson(json)
|
||||||
|
} catch (error) {
|
||||||
|
if (silent === true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logError(`加载${name}动态失败, error = ${error}`)
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return Object.assign({
|
||||||
|
loading: true,
|
||||||
|
}, dataObject)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchData()
|
||||||
|
componentUpdate = async () => await this.fetchData(true)
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
componentUpdate = async () => { }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class Activities extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.noPadding = true
|
||||||
|
this.href = settings.oldTweets ? 'https://www.bilibili.com/account/dynamic' : 'https://t.bilibili.com/'
|
||||||
|
this.html = '动态'
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<div class="activity-popup">
|
||||||
|
<activity-tabs :tab.sync="selectedTab" :items="tabs"></activity-tabs>
|
||||||
|
<div class="activity-popup-content">
|
||||||
|
<transition name="activity-content" mode="out-in">
|
||||||
|
<component :is="content"></component>
|
||||||
|
</transition>
|
||||||
|
<!-- <a class="view-more" target="_blank" :href="viewMoreUrl">查看更多<i class="mdi mdi-dots-horizontal-circle-outline"></i></a> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
this.active = document.URL.replace(/\?.*$/, '') === this.href
|
||||||
|
this.initialPopup = () => {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
this.onPopup = () => {
|
||||||
|
this.setNotifyCount(0)
|
||||||
|
}
|
||||||
|
this.getNotifyCount()
|
||||||
|
setInterval(async () => {
|
||||||
|
await this.getNotifyCount()
|
||||||
|
await tabUpdate()
|
||||||
|
await componentUpdate()
|
||||||
|
}, Activities.updateInterval)
|
||||||
|
}
|
||||||
|
static get updateInterval() {
|
||||||
|
return 5 * 60 * 1000 // 每5分钟更新1次动态提醒数字
|
||||||
|
}
|
||||||
|
static getLatestID() {
|
||||||
|
return document.cookie.replace(new RegExp(`(?:(?:^|.*;\\s*)bp_t_offset_${getUID()}\\s*\\=\\s*([^;]*).*$)|^.*$`), '$1')
|
||||||
|
}
|
||||||
|
static setLatestID(id: string) {
|
||||||
|
const currentID = Activities.getLatestID()
|
||||||
|
if (Activities.compareID(id, currentID) < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
document.cookie = `bp_t_offset_${getUID()}=${id};path=/;domain=.bilibili.com;max-age=${60 * 60 * 24 * 30}`
|
||||||
|
}
|
||||||
|
static compareID(a: string, b: string) {
|
||||||
|
if (a === b) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if (a.length > b.length) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if (b.length > a.length) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return a > b === true ? 1 : -1
|
||||||
|
}
|
||||||
|
static isNewID(id: string) {
|
||||||
|
return Activities.compareID(id, latestID) > 0
|
||||||
|
}
|
||||||
|
static updateLatestID(cards: { id: string }[]) {
|
||||||
|
const [id] = [...cards.map(c => c.id)].sort(Activities.compareID).reverse()
|
||||||
|
Activities.setLatestID(id)
|
||||||
|
}
|
||||||
|
async getNotifyCount() {
|
||||||
|
const api = `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_num?rsp_type=1&uid=${getUID()}&update_num_dy_id=${Activities.getLatestID()}&type_list=8,64,512`
|
||||||
|
const json = await Ajax.getJsonWithCredentials(api)
|
||||||
|
if (json.code !== 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.setNotifyCount(json.data.update_num)
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
Vue.component('activity-loading', {
|
||||||
|
template: /*html*/`
|
||||||
|
<div v-if="loading" class="loading">
|
||||||
|
<i class="mdi mdi-18px mdi-loading mdi-spin"></i>加载中...
|
||||||
|
</div>`,
|
||||||
|
props: ['loading'],
|
||||||
|
})
|
||||||
|
Vue.component('activity-empty', {
|
||||||
|
template: /*html*/`
|
||||||
|
<div class="empty">空空如也哦 = ̄ω ̄=</div>`,
|
||||||
|
})
|
||||||
|
new Vue({
|
||||||
|
el: await SpinQuery.select('.activity-popup') as HTMLElement,
|
||||||
|
data: {
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
name: '视频',
|
||||||
|
component: 'video-activity',
|
||||||
|
moreUrl: 'https://t.bilibili.com/?tab=8',
|
||||||
|
get notifyApi() {
|
||||||
|
return `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_num?rsp_type=1&uid=${getUID()}&update_num_dy_id=${Activities.getLatestID()}&type_list=8`
|
||||||
|
},
|
||||||
|
notifyCount: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '番剧',
|
||||||
|
component: 'bangumi-activity',
|
||||||
|
moreUrl: 'https://t.bilibili.com/?tab=512',
|
||||||
|
get notifyApi() {
|
||||||
|
return `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_num?rsp_type=1&uid=${getUID()}&update_num_dy_id=${Activities.getLatestID()}&type_list=512`
|
||||||
|
},
|
||||||
|
notifyCount: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '专栏',
|
||||||
|
component: 'column-activity',
|
||||||
|
moreUrl: 'https://t.bilibili.com/?tab=64',
|
||||||
|
get notifyApi() {
|
||||||
|
return `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_num?rsp_type=1&uid=${getUID()}&update_num_dy_id=${Activities.getLatestID()}&type_list=64`
|
||||||
|
},
|
||||||
|
notifyCount: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直播',
|
||||||
|
component: 'live-activity',
|
||||||
|
moreUrl: 'https://link.bilibili.com/p/center/index#/user-center/follow/1',
|
||||||
|
notifyCount: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selectedTab: '视频',
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'activity-tabs': {
|
||||||
|
props: ['items', 'tab'],
|
||||||
|
template: /*html*/`
|
||||||
|
<ul class="activity-tabs">
|
||||||
|
<li v-for="item of items" class="activity-tab" :data-count="item.notifyCount" :class="{selected: item.name === tab}" @click="changeTab(item)">
|
||||||
|
<div class="tab-name">{{item.name}}</div>
|
||||||
|
</li>
|
||||||
|
<a class="view-all" target="_blank" href="${settings.oldTweets ? 'https://www.bilibili.com/account/dynamic' : 'https://t.bilibili.com/'}">
|
||||||
|
全部动态
|
||||||
|
<i class="custom-navbar-iconfont-new-home custom-navbar-icon-activity"></i>
|
||||||
|
</a>
|
||||||
|
</ul>
|
||||||
|
`,
|
||||||
|
methods: {
|
||||||
|
changeTab(item: ActivityTab) {
|
||||||
|
if (this.tab === item.name) {
|
||||||
|
window.open(item.moreUrl, '_blank')
|
||||||
|
}
|
||||||
|
this.$emit('update:tab', item.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'video-activity': Object.assign(getActivityTabComponent({
|
||||||
|
dataObject: {
|
||||||
|
leftCards: [],
|
||||||
|
rightCards: [],
|
||||||
|
},
|
||||||
|
apiUrl: `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=8`,
|
||||||
|
name: '视频',
|
||||||
|
template: /*html*/`
|
||||||
|
<div class="video-activity" :class="{center: loading || (leftCards.length + rightCards.length) === 0}">
|
||||||
|
<activity-loading :loading="loading"></activity-loading>
|
||||||
|
<activity-empty v-if="!loading && leftCards.length + rightCards.length === 0"></activity-empty>
|
||||||
|
<div v-if="!loading" class="video-activity-column">
|
||||||
|
<video-card v-for="card of leftCards" :key="card.id" :card="card" :watchlaterInit="card.watchlater"></video-card>
|
||||||
|
</div>
|
||||||
|
<div v-if="!loading" class="video-activity-column">
|
||||||
|
<video-card v-for="card of rightCards" :key="card.id" :card="card" :watchlaterInit="card.watchlater"></video-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
handleJson: async function (json) {
|
||||||
|
// const { getWatchlaterList } = await import('../../video/watchlater-api')
|
||||||
|
// const watchlaterList = await getWatchlaterList()
|
||||||
|
const cards = json.data.cards.map((card: any) => {
|
||||||
|
const cardJson = JSON.parse(card.card)
|
||||||
|
return {
|
||||||
|
coverUrl: cardJson.pic,
|
||||||
|
title: cardJson.title,
|
||||||
|
timeNumber: cardJson.duration,
|
||||||
|
time: formatDuration(cardJson.duration),
|
||||||
|
description: cardJson.desc,
|
||||||
|
aid: cardJson.aid,
|
||||||
|
videoUrl: `https://www.bilibili.com/av${cardJson.aid}`,
|
||||||
|
faceUrl: card.desc.user_profile.info.face,
|
||||||
|
upName: card.desc.user_profile.info.uname,
|
||||||
|
upUrl: `https://space.bilibili.com/${card.desc.user_profile.info.uid}`,
|
||||||
|
id: card.desc.dynamic_id_str,
|
||||||
|
watchlater: true,
|
||||||
|
get new() { return Activities.isNewID(this.id) },
|
||||||
|
}
|
||||||
|
}) as []
|
||||||
|
this.leftCards = cards.filter((_, index) => index % 2 === 0)
|
||||||
|
this.rightCards = cards.filter((_, index) => index % 2 === 1)
|
||||||
|
if (this.leftCards.length !== this.rightCards.length) {
|
||||||
|
this.leftCards.pop()
|
||||||
|
}
|
||||||
|
Activities.updateLatestID(cards)
|
||||||
|
}
|
||||||
|
}), {
|
||||||
|
components: {
|
||||||
|
'video-card': {
|
||||||
|
props: ['card', 'watchlaterInit'],
|
||||||
|
store,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// watchlater: this.watchlaterInit,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...Vuex.mapState(['watchlaterList']),
|
||||||
|
watchlater() {
|
||||||
|
if (this.watchlaterInit !== null) {
|
||||||
|
return this.watchlaterList.includes(this.card.aid)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'dpi-img': () => import('../dpi-img.vue'),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...Vuex.mapActions(['toggleWatchlater']),
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
// 预加载稍后再看的API
|
||||||
|
// await import('../../video/watchlater-api')
|
||||||
|
},
|
||||||
|
template: /*html*/`
|
||||||
|
<a class="video-activity-card" :class="{new: card.new}" target="_blank" :href="card.videoUrl">
|
||||||
|
<div class="cover-container">
|
||||||
|
<dpi-img class="cover" :size="{width: 172}" :src="card.coverUrl"></dpi-img>
|
||||||
|
<div class="time">{{card.time}}</div>
|
||||||
|
<div @click.stop.prevent="toggleWatchlater(card.aid)" class="watchlater"><i class="mdi" :class="{'mdi-clock-outline': !watchlater, 'mdi-check-circle': watchlater}"></i>{{watchlater ? '已添加' : '稍后再看'}}</div>
|
||||||
|
</div>
|
||||||
|
<h1 class="title" :title="card.title">{{card.title}}</h1>
|
||||||
|
<a class="up" target="_blank" :href="card.upUrl" :title="card.upName">
|
||||||
|
<dpi-img class="face" :size="24" :src="card.faceUrl"></dpi-img>
|
||||||
|
<span class="name">{{card.upName}}</span>
|
||||||
|
</a>
|
||||||
|
</a>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'bangumi-activity': getActivityTabComponent({
|
||||||
|
dataObject: { cards: [] },
|
||||||
|
apiUrl: `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=512`,
|
||||||
|
name: '番剧',
|
||||||
|
template: /*html*/`
|
||||||
|
<div class="bangumi-activity" :class="{center: loading || cards.length === 0}">
|
||||||
|
<activity-loading :loading="loading"></activity-loading>
|
||||||
|
<activity-empty v-if="!loading && cards.length === 0"></activity-empty>
|
||||||
|
<a v-if="!loading" class="bangumi-card" :class="{new: card.new}" v-for="card of cards" :key="card.id" target="_blank" :href="card.url">
|
||||||
|
<dpi-img class="ep-cover" :size="{width: 100}" :src="card.epCoverUrl"></dpi-img>
|
||||||
|
<h1 class="ep-title" :title="card.epTitle">{{card.epTitle}}</h1>
|
||||||
|
<div class="up" :title="card.title">
|
||||||
|
<dpi-img class="cover" :size="24" :src="card.coverUrl"></dpi-img>
|
||||||
|
<div class="title">{{card.title}}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
handleJson: async function (json) {
|
||||||
|
this.cards = json.data.cards.map((card: any) => {
|
||||||
|
const cardJson = JSON.parse(card.card)
|
||||||
|
return {
|
||||||
|
title: cardJson.apiSeasonInfo.title,
|
||||||
|
coverUrl: cardJson.apiSeasonInfo.cover,
|
||||||
|
epCoverUrl: cardJson.cover,
|
||||||
|
epTitle: cardJson.new_desc,
|
||||||
|
url: cardJson.url,
|
||||||
|
id: card.desc.dynamic_id_str,
|
||||||
|
get new() { return Activities.isNewID(this.id) },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Activities.updateLatestID(this.cards)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'column-activity': getActivityTabComponent({
|
||||||
|
dataObject: { cards: [] },
|
||||||
|
apiUrl: `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=64`,
|
||||||
|
name: '专栏',
|
||||||
|
template: /*html*/`
|
||||||
|
<div class="column-activity" :class="{center: loading || cards.length === 0}">
|
||||||
|
<activity-loading :loading="loading"></activity-loading>
|
||||||
|
<activity-empty v-if="!loading && cards.length === 0"></activity-empty>
|
||||||
|
<a v-if="!loading" class="column-card" :class="{new: card.new}" v-for="card of cards" :key="card.id" target="_blank" :href="card.url">
|
||||||
|
<div class="covers">
|
||||||
|
<dpi-img class="cover" v-for="cover of card.covers" :key="cover" :size="{height: 120}" :src="cover"></dpi-img>
|
||||||
|
<a class="up" target="_blank" :href="card.upUrl">
|
||||||
|
<dpi-img class="face" :size="24" :src="card.faceUrl"></dpi-img>
|
||||||
|
<div class="name">{{card.upName}}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<h1 class="title" :title="card.title">{{card.title}}</h1>
|
||||||
|
<div class="description" :title="card.description">{{card.description}}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
handleJson: async function (json) {
|
||||||
|
this.cards = json.data.cards.map((card: any) => {
|
||||||
|
const cardJson = JSON.parse(card.card)
|
||||||
|
return {
|
||||||
|
covers: cardJson.image_urls,
|
||||||
|
originalCovers: cardJson.origin_image_urls,
|
||||||
|
upName: cardJson.author.name,
|
||||||
|
faceUrl: cardJson.author.face,
|
||||||
|
upUrl: `https://space.bilibili.com/${cardJson.author.mid}`,
|
||||||
|
title: cardJson.title,
|
||||||
|
description: cardJson.summary,
|
||||||
|
url: `https://www.bilibili.com/read/cv${cardJson.id}`,
|
||||||
|
id: card.desc.dynamic_id_str,
|
||||||
|
get new() { return Activities.isNewID(this.id) },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Activities.updateLatestID(this.cards)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'live-activity': getActivityTabComponent({
|
||||||
|
dataObject: { cards: [] },
|
||||||
|
apiUrl: `https://api.live.bilibili.com/relation/v1/feed/feed_list?page=1&pagesize=24`,
|
||||||
|
name: '直播',
|
||||||
|
template: /*html*/`
|
||||||
|
<div class="live-activity" :class="{center: loading || cards.length === 0}">
|
||||||
|
<activity-loading :loading="loading"></activity-loading>
|
||||||
|
<activity-empty v-if="!loading && cards.length === 0"></activity-empty>
|
||||||
|
<a v-if="!loading" class="live-card" v-for="card of cards" :key="card.id" target="_blank" :href="card.url">
|
||||||
|
<dpi-img class="face" :size="{width: 48}" :src="card.faceUrl"></dpi-img>
|
||||||
|
<h1 class="live-title" :title="card.title">{{card.title}}</h1>
|
||||||
|
<div class="name" :title="card.name">{{card.name}}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
handleJson: async function (json) {
|
||||||
|
this.cards = json.data.list.map((card: any) => {
|
||||||
|
return {
|
||||||
|
faceUrl: card.face,
|
||||||
|
title: card.title,
|
||||||
|
name: card.uname,
|
||||||
|
id: card.roomid,
|
||||||
|
url: card.link,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
content() {
|
||||||
|
return this.tabs.find((tab: ActivityTab) => tab.name === this.selectedTab).component
|
||||||
|
},
|
||||||
|
viewMoreUrl() {
|
||||||
|
return this.tabs.find((tab: ActivityTab) => tab.name === this.selectedTab).moreUrl
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
tabUpdate = async () => {
|
||||||
|
for (const tab of this.tabs) {
|
||||||
|
if (tab.notifyApi) {
|
||||||
|
const json = await Ajax.getJsonWithCredentials(tab.notifyApi)
|
||||||
|
if (json.code !== 0 || !json.data.update_num || this.selectedTab === tab.name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tab.notifyCount = json.data.update_num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabUpdate()
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
tabUpdate = async () => { }
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectedTab(name) {
|
||||||
|
this.tabs.find((t: ActivityTab) => t.name === name).notifyCount = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'activities'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
latestID = Activities.getLatestID()
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Activities,
|
||||||
|
},
|
||||||
|
}
|
||||||
152
src/style/custom-navbar/category/custom-navbar-category.ts
Normal file
152
src/style/custom-navbar/category/custom-navbar-category.ts
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
|
||||||
|
export class Category extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.html = `主站`
|
||||||
|
// this.requestedPopup = true
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<ul id="custom-navbar-home-popup">
|
||||||
|
<li class="category-item loading" v-if="loading">
|
||||||
|
加载中...
|
||||||
|
</li>
|
||||||
|
<li class="category-item" style="display: none" :style="{display: loading ? 'none' : 'list-item'}" v-for="item of info" :class="{ main: item[1].count }">
|
||||||
|
<a :href="item[1].link">
|
||||||
|
<svg aria-hidden="true">
|
||||||
|
<use :href="'#header-icon-' + item[1].icon" :xlink:href="'#header-icon-' + item[1].icon"></use>
|
||||||
|
</svg>
|
||||||
|
<div>{{item[0]}}</div>
|
||||||
|
<span>{{item[1].count}}</span>
|
||||||
|
</a>
|
||||||
|
<div class="popup" v-if="item[1].subRegions">
|
||||||
|
<a v-for="region of Object.entries(item[1].subRegions)" :href="region[1]">
|
||||||
|
{{region[0]}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
const getOnlineInfo = async () => {
|
||||||
|
const json = await Ajax.getJson('https://api.bilibili.com/x/web-interface/online')
|
||||||
|
if (parseInt(json.code) !== 0) {
|
||||||
|
throw new Error(`[自定义顶栏] 分区投稿信息获取失败: ${json.message}`)
|
||||||
|
}
|
||||||
|
const regionCount = json.data.region_count
|
||||||
|
await SpinQuery.select('#custom-navbar-home-popup')
|
||||||
|
return {
|
||||||
|
动画: {
|
||||||
|
icon: 'douga',
|
||||||
|
count: regionCount[1], link: `https://www.bilibili.com/v/douga/`,
|
||||||
|
subRegions: {
|
||||||
|
'MAD·AMV': `https://www.bilibili.com/v/douga/mad/`,
|
||||||
|
'MMD·3D': `https://www.bilibili.com/v/douga/mmd/`,
|
||||||
|
'短片·手书·配音': `https://www.bilibili.com/v/douga/voice/`,
|
||||||
|
'综合': `https://www.bilibili.com/v/douga/other/`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
番剧: {
|
||||||
|
icon: 'anime',
|
||||||
|
count: regionCount[13], link: `https://www.bilibili.com/anime/`,
|
||||||
|
subRegions: {
|
||||||
|
'连载动画': `https://www.bilibili.com/v/anime/serial/`,
|
||||||
|
'完结动画': `https://www.bilibili.com/v/anime/finish/`,
|
||||||
|
'资讯': `https://www.bilibili.com/v/anime/information/`,
|
||||||
|
'官方延伸': `https://www.bilibili.com/v/anime/offical/`,
|
||||||
|
'新番时间表': `https://www.bilibili.com/anime/timeline/`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
国创: {
|
||||||
|
icon: 'guochuang',
|
||||||
|
count: regionCount[167], link: `https://www.bilibili.com/guochuang/`,
|
||||||
|
subRegions: {
|
||||||
|
'国产动画': `https://www.bilibili.com/v/guochuang/chinese/`,
|
||||||
|
'国产原创相关': `https://www.bilibili.com/v/guochuang/original/`,
|
||||||
|
'布袋戏': `https://www.bilibili.com/v/guochuang/puppetry/`,
|
||||||
|
'资讯': `https://www.bilibili.com/v/guochuang/information/`,
|
||||||
|
'新番时间表': `https://www.bilibili.com/guochuang/timeline/`,
|
||||||
|
'国产动画索引': `https://www.bilibili.com/guochuang/index/`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
音乐: {
|
||||||
|
icon: 'music',
|
||||||
|
count: regionCount[3], link: `https://www.bilibili.com/v/music/`,
|
||||||
|
subRegions: {
|
||||||
|
'原创音乐': 'https://www.bilibili.com/v/music/original/',
|
||||||
|
'翻唱': 'https://www.bilibili.com/v/music/cover/',
|
||||||
|
'VOCALOID·UTAU': 'https://www.bilibili.com/v/music/vocaloid/',
|
||||||
|
'电音': 'https://www.bilibili.com/v/music/electronic/',
|
||||||
|
'演奏': 'https://www.bilibili.com/v/music/perform/',
|
||||||
|
'MV': 'https://www.bilibili.com/v/music/mv/',
|
||||||
|
'音乐现场': 'https://www.bilibili.com/v/music/live/',
|
||||||
|
'音乐综合': 'https://www.bilibili.com/v/music/other/',
|
||||||
|
'音频': 'https://www.bilibili.com/audio/home?musicType=music',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
舞蹈: {
|
||||||
|
icon: 'dance',
|
||||||
|
count: regionCount[129], link: `https://www.bilibili.com/v/dance/`, subRegions: { '宅舞': 'https://www.bilibili.com/v/dance/otaku/', '三次元舞蹈': 'https://www.bilibili.com/v/dance/three_d/', '舞蹈教程': 'https://www.bilibili.com/v/dance/demo/' },
|
||||||
|
},
|
||||||
|
游戏: {
|
||||||
|
icon: 'game',
|
||||||
|
count: regionCount[4], link: `https://www.bilibili.com/v/game/`, subRegions: { '单机游戏': 'https://www.bilibili.com/v/game/stand_alone/', '电子竞技': 'https://www.bilibili.com/v/game/esports/', '手机游戏': 'https://www.bilibili.com/v/game/mobile/', '网络游戏': 'https://www.bilibili.com/v/game/online/', '桌游棋牌': 'https://www.bilibili.com/v/game/board/', 'GMV': 'https://www.bilibili.com/v/game/gmv/', '音游': 'https://www.bilibili.com/v/game/music/', 'Mugen': 'https://www.bilibili.com/v/game/mugen/', '游戏赛事': 'https://www.bilibili.com/v/game/match/' },
|
||||||
|
},
|
||||||
|
科技: {
|
||||||
|
icon: 'technology',
|
||||||
|
count: regionCount[36], link: `https://www.bilibili.com/v/technology/`, subRegions: { '趣味科普人文': 'https://www.bilibili.com/v/technology/fun/', '野生技术协会': 'https://www.bilibili.com/v/technology/wild/', '演讲·公开课': 'https://www.bilibili.com/v/technology/speech_course/', '星海': 'https://www.bilibili.com/v/technology/military/', '机械': 'https://www.bilibili.com/v/technology/mechanical/', '汽车': 'https://www.bilibili.com/v/technology/automobile/' },
|
||||||
|
},
|
||||||
|
数码: { icon: 'digital', count: regionCount[188], link: `https://www.bilibili.com/v/digital/`, subRegions: { '手机平板': 'https://www.bilibili.com/v/digital/mobile/', '电脑装机': 'https://www.bilibili.com/v/digital/pc/', '摄影摄像': 'https://www.bilibili.com/v/digital/photography/', '影音智能': 'https://www.bilibili.com/v/digital/intelligence_av/' }, },
|
||||||
|
生活: {
|
||||||
|
icon: 'life',
|
||||||
|
count: regionCount[160], link: `https://www.bilibili.com/v/life/`, subRegions: { '搞笑': 'https://www.bilibili.com/v/life/funny/', '日常': 'https://www.bilibili.com/v/life/daily/', '美食圈': 'https://www.bilibili.com/v/life/food/', '动物圈': 'https://www.bilibili.com/v/life/animal/', '手工': 'https://www.bilibili.com/v/life/handmake/', '绘画': 'https://www.bilibili.com/v/life/painting/', '运动': 'https://www.bilibili.com/v/life/sports/', '其他': 'https://www.bilibili.com/v/life/other/' },
|
||||||
|
},
|
||||||
|
鬼畜: {
|
||||||
|
icon: 'kichiku',
|
||||||
|
count: regionCount[119], link: `https://www.bilibili.com/v/kichiku/`, subRegions: { '鬼畜调教': 'https://www.bilibili.com/v/kichiku/guide/', '音MAD': 'https://www.bilibili.com/v/kichiku/mad/', '人力VOCALOID': 'https://www.bilibili.com/v/kichiku/manual_vocaloid/', '教程演示': 'https://www.bilibili.com/v/kichiku/course/' },
|
||||||
|
},
|
||||||
|
时尚: { icon: 'fashion', count: regionCount[155], link: `https://www.bilibili.com/v/fashion/`, subRegions: { '美妆': 'https://www.bilibili.com/v/fashion/makeup/', '服饰': 'https://www.bilibili.com/v/fashion/clothing/', '健身': 'https://www.bilibili.com/v/fashion/aerobics/', 'T台': 'https://www.bilibili.com/v/fashion/catwalk/', '风尚标': 'https://www.bilibili.com/v/fashion/trends/' }, },
|
||||||
|
广告: { icon: 'ad', count: regionCount[165], link: `https://www.bilibili.com/v/ad/ad/`, },
|
||||||
|
娱乐: {
|
||||||
|
icon: 'ent',
|
||||||
|
count: regionCount[5], link: `https://www.bilibili.com/v/ent/`, subRegions: { '综艺': 'https://www.bilibili.com/v/ent/variety/', '明星': 'https://www.bilibili.com/v/ent/star/', 'Korea相关': 'https://www.bilibili.com/v/ent/korea/' },
|
||||||
|
},
|
||||||
|
影视: {
|
||||||
|
icon: 'cinephile',
|
||||||
|
count: regionCount[181], link: `https://www.bilibili.com/v/cinephile/`, subRegions: { '影视杂谈': 'https://www.bilibili.com/v/cinephile/cinecism/', '影视剪辑': 'https://www.bilibili.com/v/cinephile/montage/', '短片': 'https://www.bilibili.com/v/cinephile/shortfilm/', '预告·资讯': 'https://www.bilibili.com/v/cinephile/trailer_info/', '特摄': 'https://www.bilibili.com/v/cinephile/tokusatsu/' },
|
||||||
|
},
|
||||||
|
放映厅: { icon: 'cinema', count: regionCount[177] + regionCount[23] + regionCount[11], link: `https://www.bilibili.com/cinema/`, subRegions: { '纪录片': 'https://www.bilibili.com/documentary/', '电影': 'https://www.bilibili.com/movie/', '电视剧': 'https://www.bilibili.com/tv/' }, },
|
||||||
|
专栏: { icon: 'read', count: ``, link: `https://www.bilibili.com/read/home`, },
|
||||||
|
直播: {
|
||||||
|
icon: 'zhibo',
|
||||||
|
count: ``, link: `https://live.bilibili.com`, subRegions: { '全部直播': 'https://live.bilibili.com/all?visit_id=5icxsa0kmts0', '游戏直播': 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=2&areaId=0&visit_id=5icxsa0kmts0#/2/0', '手游直播': 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=3&areaId=0&visit_id=5icxsa0kmts0#/3/0', '娱乐直播': 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=1&areaId=0&visit_id=5icxsa0kmts0#/1/0', '电台直播': 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=5&areaId=0&visit_id=5icxsa0kmts0#/5/0', '绘画直播': 'https://live.bilibili.com/p/eden/area-tags?parentAreaId=4&areaId=0&visit_id=5icxsa0kmts0#/4/0' },
|
||||||
|
},
|
||||||
|
小黑屋: { icon: 'blackroom', count: ``, link: `https://www.bilibili.com/blackroom/`, },
|
||||||
|
专题: { icon: 'topic', count: ``, link: `https://www.bilibili.com/blackboard/topic_list.html`, },
|
||||||
|
活动: { icon: 'activit', count: ``, link: `https://www.bilibili.com/blackboard/x/act_list`, },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.initialPopup = async () => {
|
||||||
|
new Vue({
|
||||||
|
el: await SpinQuery.select('#custom-navbar-home-popup') as HTMLElement,
|
||||||
|
data: {
|
||||||
|
info: [],
|
||||||
|
loading: true,
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
try {
|
||||||
|
this.info = Object.entries(await getOnlineInfo())
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'category'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Category,
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
type PopupAction = (() => void) | null
|
type PopupAction = (() => void) | null
|
||||||
export class NavbarComponent {
|
export class NavbarComponent {
|
||||||
public noPadding = false
|
public noPadding = false
|
||||||
|
public transparent = false
|
||||||
constructor(
|
constructor(
|
||||||
public html = '',
|
public html = '',
|
||||||
public popupHtml = '',
|
public popupHtml = '',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -837,7 +837,7 @@ li.nav-item[report-id="playpage_dynamic"] .i-frame,
|
|||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@import "_activity-popup", "_subscriptions", "_round-corner", "_custom-navbar-settings", "_home-popup", "_watchlater-list";
|
@import "./activities/activities", "./subscriptions/subscriptions", "_round-corner", "./settings/settings", "./category/category", "./watchlater-list/watchlater-list";
|
||||||
|
|
||||||
.custom-navbar > ul > li:not(.disabled):hover > .popup,
|
.custom-navbar > ul > li:not(.disabled):hover > .popup,
|
||||||
#custom-navbar-home-popup .category-item:hover .popup,
|
#custom-navbar-home-popup .category-item:hover .popup,
|
||||||
|
|||||||
175
src/style/custom-navbar/custom-navbar.ts
Normal file
175
src/style/custom-navbar/custom-navbar.ts
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import { NavbarComponent } from './custom-navbar-component'
|
||||||
|
const supportedUrls = [
|
||||||
|
'//www.bilibili.com',
|
||||||
|
'//t.bilibili.com',
|
||||||
|
'//search.bilibili.com',
|
||||||
|
'//space.bilibili.com',
|
||||||
|
'//account.bilibili.com',
|
||||||
|
'//pay.bilibili.com',
|
||||||
|
'//member.bilibili.com',
|
||||||
|
'//big.bilibili.com',
|
||||||
|
'//message.bilibili.com',
|
||||||
|
'//app.bilibili.com',
|
||||||
|
'//passport.bilibili.com',
|
||||||
|
'//game.bilibili.com',
|
||||||
|
'//live.bilibili.com/blackboard/'
|
||||||
|
]
|
||||||
|
const unsupportedUrls = [
|
||||||
|
'//t.bilibili.com/lottery/h5/index/#/result',
|
||||||
|
'//member.bilibili.com/video/upload',
|
||||||
|
'//space.bilibili.com/ajax/',
|
||||||
|
'//www.bilibili.com/h5/comment/',
|
||||||
|
]
|
||||||
|
const loadSettings = () => {
|
||||||
|
document.body.style.setProperty('--navbar-bounds-padding', `0 ${settings.customNavbarBoundsPadding}%`)
|
||||||
|
document.body.style.setProperty('--navbar-blur-opacity', (settings.customNavbarBlurOpacity || 0.7).toString())
|
||||||
|
addSettingsListener('customNavbarBlurOpacity', value => {
|
||||||
|
document.body.style.setProperty('--navbar-blur-opacity', value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const classHandler = (key: string, value: boolean, element: HTMLElement) => {
|
||||||
|
element.classList.toggle(key, value)
|
||||||
|
}
|
||||||
|
const darkHandler = (force: boolean) => {
|
||||||
|
(dq('.custom-navbar') as HTMLElement).classList.toggle('dark', force);
|
||||||
|
(dq('.custom-navbar-settings') as HTMLElement).classList.toggle('dark', force)
|
||||||
|
}
|
||||||
|
export default (() => {
|
||||||
|
if (isIframe()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loadSettings()
|
||||||
|
const showWidget = !(!supportedUrls.some(it => document.URL.includes(it))
|
||||||
|
|| unsupportedUrls.some(it => document.URL.includes(it)))
|
||||||
|
if (showWidget) {
|
||||||
|
document.body.classList.add('custom-navbar-loading');
|
||||||
|
(async () => {
|
||||||
|
const html = await import((() => 'customNavbarHtml')())
|
||||||
|
document.body.insertAdjacentHTML('beforeend', html)
|
||||||
|
addSettingsListener('useDarkStyle', darkHandler, true)
|
||||||
|
const getNavbarElement = () => dq('.custom-navbar') as HTMLElement
|
||||||
|
['Fill', 'Shadow', 'Compact', 'Blur'].forEach(item => {
|
||||||
|
const key = 'customNavbar' + item as keyof BilibiliEvolvedSettings
|
||||||
|
addSettingsListener(
|
||||||
|
key,
|
||||||
|
value => classHandler(item.toLowerCase(), value, getNavbarElement()),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
SpinQuery.condition(() => dq('#banner_link,.international-header .bili-banner'),
|
||||||
|
banner => banner === null ? false : Boolean((banner as HTMLElement).style.backgroundImage),
|
||||||
|
(banner: HTMLElement) => {
|
||||||
|
Observer.attributes(banner, () => {
|
||||||
|
const blurLayers = dqa('.custom-navbar .blur-layer') as HTMLElement[]
|
||||||
|
blurLayers.forEach(blurLayer => {
|
||||||
|
blurLayer.style.backgroundImage = banner.style.backgroundImage
|
||||||
|
blurLayer.setAttribute('data-image', banner.style.backgroundImage)
|
||||||
|
})
|
||||||
|
addSettingsListener('customNavbarTransparent', value => {
|
||||||
|
if (!settings.hideBanner) {
|
||||||
|
getNavbarElement().classList.toggle('transparent', value)
|
||||||
|
}
|
||||||
|
}, true)
|
||||||
|
addSettingsListener('hideBanner', value => {
|
||||||
|
if (settings.customNavbarTransparent) {
|
||||||
|
getNavbarElement().classList.toggle('transparent', !value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const { Blank } = await import('./simple/custom-navbar-blank')
|
||||||
|
const { Logo } = await import('./simple/custom-navbar-logo')
|
||||||
|
const { Category } = await import('./category/custom-navbar-category')
|
||||||
|
const { SimpleLink } = await import('./simple/custom-navbar-simple-link')
|
||||||
|
const { UserInfo } = await import('./simple/custom-navbar-user-info')
|
||||||
|
const { SearchBox } = await import('./simple/custom-navbar-search-box')
|
||||||
|
const { Iframe } = await import('./simple/custom-navbar-iframe')
|
||||||
|
const components = [
|
||||||
|
new Blank(1),
|
||||||
|
new Logo(),
|
||||||
|
new Category(),
|
||||||
|
new SimpleLink('排行', 'https://www.bilibili.com/ranking', 'ranking'),
|
||||||
|
new SimpleLink('相簿', 'https://h.bilibili.com', 'drawing'),
|
||||||
|
new SimpleLink('音频', 'https://www.bilibili.com/audio/home/', 'music'),
|
||||||
|
new Iframe('游戏中心', 'https://game.bilibili.com/', {
|
||||||
|
src: `https://www.bilibili.com/page-proxy/game-nav.html`,
|
||||||
|
width: `680px`,
|
||||||
|
height: `260px`,
|
||||||
|
lazy: true,
|
||||||
|
iframeName: 'games',
|
||||||
|
}),
|
||||||
|
new Iframe('直播', 'https://live.bilibili.com', {
|
||||||
|
src: `https://live.bilibili.com/blackboard/dropdown-menu.html`,
|
||||||
|
width: `528px`,
|
||||||
|
height: `266px`,
|
||||||
|
lazy: true,
|
||||||
|
iframeName: 'lives',
|
||||||
|
}),
|
||||||
|
new SimpleLink('会员购', 'https://show.bilibili.com', 'shop'),
|
||||||
|
new SimpleLink('漫画', 'https://manga.bilibili.com', 'manga'),
|
||||||
|
new Blank(2),
|
||||||
|
new SearchBox(),
|
||||||
|
new UserInfo(),
|
||||||
|
]
|
||||||
|
if (getUID()) {
|
||||||
|
const { WatchlaterList } = await import('./watchlater-list/custom-navbar-watchlater-list')
|
||||||
|
const { Messages } = await import('./simple/custom-navbar-messages')
|
||||||
|
const { Activities } = await import('./activities/custom-navbar-activities')
|
||||||
|
const { Subscriptions } = await import('./subscriptions/custom-navbar-subscriptions')
|
||||||
|
const { FavoritesList, HistoryList } = await import('./simple/custom-navbar-video-list')
|
||||||
|
components.push(
|
||||||
|
new Messages(),
|
||||||
|
new Subscriptions(),
|
||||||
|
new Activities(),
|
||||||
|
new WatchlaterList(),
|
||||||
|
new FavoritesList(),
|
||||||
|
new HistoryList(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const { Upload } = await import('./simple/custom-navbar-upload')
|
||||||
|
components.push(new Upload(), new Blank(3))
|
||||||
|
new Vue({
|
||||||
|
el: '.custom-navbar',
|
||||||
|
data: {
|
||||||
|
components,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
requestPopup(component: NavbarComponent) {
|
||||||
|
if (!component.requestedPopup && !component.disabled && !component.active) {
|
||||||
|
this.$set(component, `requestedPopup`, true)
|
||||||
|
component.initialPopup && component.initialPopup()
|
||||||
|
}
|
||||||
|
component.onPopup && component.onPopup()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
document.body.classList.remove('custom-navbar-loading')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
widget: {
|
||||||
|
content: /*html*/`
|
||||||
|
<div class="gui-settings-flat-button" id="custom-navbar-settings">
|
||||||
|
<i class="mdi mdi-24px mdi-auto-fix"></i>
|
||||||
|
<span>顶栏布局</span>
|
||||||
|
</div>`,
|
||||||
|
condition: () => showWidget,
|
||||||
|
success: async () => {
|
||||||
|
const { initSettingsPanel } = await import('./settings/custom-navbar-settings')
|
||||||
|
await initSettingsPanel()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unload: () => {
|
||||||
|
const navbar = dqa('.custom-navbar,.custom-navbar-settings')
|
||||||
|
navbar.forEach((it: HTMLElement) => it.style.display = 'none')
|
||||||
|
resources.removeStyle('customNavbarStyle')
|
||||||
|
},
|
||||||
|
reload: () => {
|
||||||
|
const navbar = dqa('.custom-navbar,.custom-navbar-settings')
|
||||||
|
navbar.forEach((it: HTMLElement) => it.style.display = 'flex')
|
||||||
|
resources.applyImportantStyle('customNavbarStyle')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})()
|
||||||
@ -1,6 +1,6 @@
|
|||||||
export const initSettingsPanel = async () => {
|
export const initSettingsPanel = async () => {
|
||||||
await SpinQuery.select('.custom-navbar-settings')
|
await SpinQuery.select('.custom-navbar-settings')
|
||||||
const { Slip } = await import('../../touch/slip')
|
const { Slip } = await import('../../../touch/slip')
|
||||||
const button = dq('#custom-navbar-settings') as HTMLDivElement
|
const button = dq('#custom-navbar-settings') as HTMLDivElement
|
||||||
button.addEventListener('click', async () => {
|
button.addEventListener('click', async () => {
|
||||||
const settingsPanel = dq('.custom-navbar-settings')
|
const settingsPanel = dq('.custom-navbar-settings')
|
||||||
16
src/style/custom-navbar/simple/custom-navbar-blank.ts
Normal file
16
src/style/custom-navbar/simple/custom-navbar-blank.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export class Blank extends NavbarComponent {
|
||||||
|
constructor(public number: number) {
|
||||||
|
super()
|
||||||
|
this.flex = '1 0 auto'
|
||||||
|
this.disabled = true
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return ('blank' + this.number) as keyof CustomNavbarOrders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Blank
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/style/custom-navbar/simple/custom-navbar-iframe.ts
Normal file
33
src/style/custom-navbar/simple/custom-navbar-iframe.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export interface IframeConfig {
|
||||||
|
src: string
|
||||||
|
width: string
|
||||||
|
height: string
|
||||||
|
lazy: boolean
|
||||||
|
iframeName: string
|
||||||
|
}
|
||||||
|
export class Iframe extends NavbarComponent {
|
||||||
|
iframeName: string
|
||||||
|
constructor(name: string, link: string, config: IframeConfig) {
|
||||||
|
super()
|
||||||
|
const { src, width, height, lazy, iframeName } = config
|
||||||
|
this.iframeName = iframeName
|
||||||
|
this.html = name
|
||||||
|
this.href = link
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<iframe src='${src}' frameborder='0' width='${width}' height='${height}'></iframe>
|
||||||
|
`
|
||||||
|
this.noPadding = true
|
||||||
|
this.requestedPopup = lazy ? false : true
|
||||||
|
this.touch = false
|
||||||
|
this.transparent = true
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return (this.iframeName + 'Iframe') as keyof CustomNavbarOrders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Iframe,
|
||||||
|
},
|
||||||
|
}
|
||||||
29
src/style/custom-navbar/simple/custom-navbar-logo.ts
Normal file
29
src/style/custom-navbar/simple/custom-navbar-logo.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export class Logo extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.href = `https://www.bilibili.com/`
|
||||||
|
this.touch = false
|
||||||
|
addSettingsListener('customNavbarSeasonLogo', () => this.getLogo(), true)
|
||||||
|
}
|
||||||
|
async getLogo() {
|
||||||
|
if (settings.customNavbarSeasonLogo) {
|
||||||
|
const json = await Ajax.getJson(
|
||||||
|
'https://api.bilibili.com/x/web-show/res/locs?pf=0&ids=142'
|
||||||
|
)
|
||||||
|
if (json.code === 0) {
|
||||||
|
this.html = /*html*/`<img height="38" src="${json.data[142][0].litpic.replace('http:', 'https:')}">`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.html = /*html*/`<i class="custom-navbar-iconfont custom-navbar-icon-logo"></i>`
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'logo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Logo,
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/style/custom-navbar/simple/custom-navbar-messages.ts
Normal file
74
src/style/custom-navbar/simple/custom-navbar-messages.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export class Messages extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.href = 'https://message.bilibili.com/'
|
||||||
|
this.html = '消息'
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<ul id="message-list">
|
||||||
|
<li><a data-name="reply" target="_blank" href="https://message.bilibili.com/#/reply">回复我的</a></li>
|
||||||
|
<li><a data-name="at" target="_blank" href="https://message.bilibili.com/#/at">@我的</a></li>
|
||||||
|
<li><a data-name="like" target="_blank" href="https://message.bilibili.com/#/love">收到的赞</a></li>
|
||||||
|
<li><a data-name="user_msg" target="_blank" href="https://message.bilibili.com/#/whisper">我的消息</a></li>
|
||||||
|
<li><a data-name="sys_msg" target="_blank" href="https://message.bilibili.com/#/system">系统通知</a></li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
this.requestedPopup = true
|
||||||
|
this.active = document.URL.startsWith('https://message.bilibili.com/')
|
||||||
|
this.fetchSettings().then(notify => {
|
||||||
|
if (notify) {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'messages'
|
||||||
|
}
|
||||||
|
async fetchSettings() {
|
||||||
|
const json = await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/link_setting/v1/link_setting/get?msg_notify=1`)
|
||||||
|
if (json.code !== 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await this.setNotifyStyle(json.data.msg_notify)
|
||||||
|
return json.data.msg_notify !== 3
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
const mainJson = await Ajax.getJsonWithCredentials(`https://api.bilibili.com/x/msgfeed/unread`)
|
||||||
|
const messageJson = await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/session_svr/v1/session_svr/single_unread`)
|
||||||
|
const list = await SpinQuery.select('#message-list') as HTMLElement
|
||||||
|
const items = [...list.querySelectorAll('a[data-name]')]
|
||||||
|
const names = items.map(it => it.getAttribute('data-name')!!)
|
||||||
|
|
||||||
|
if (mainJson.code !== 0 || messageJson.code !== 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mainJson.data['user_msg'] = messageJson.data.unfollow_unread + messageJson.data.follow_unread
|
||||||
|
let totalCount: number = names.reduce((acc, it) => acc + mainJson.data[it], 0)
|
||||||
|
if (!totalCount) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await this.setNotifyCount(totalCount)
|
||||||
|
names.forEach((name, index) => {
|
||||||
|
const count = mainJson.data[name] as number
|
||||||
|
if (count > 0) {
|
||||||
|
items[index].setAttribute('data-count', count.toString())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
items[index].removeAttribute('data-count')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
items.forEach(item => {
|
||||||
|
item.addEventListener('click', () => {
|
||||||
|
const count = parseInt(item.getAttribute('data-count')!!)
|
||||||
|
item.removeAttribute('data-count')
|
||||||
|
totalCount -= count
|
||||||
|
this.setNotifyCount(totalCount)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Messages,
|
||||||
|
},
|
||||||
|
}
|
||||||
189
src/style/custom-navbar/simple/custom-navbar-search-box.ts
Normal file
189
src/style/custom-navbar/simple/custom-navbar-search-box.ts
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
interface SuggestItem {
|
||||||
|
value: string
|
||||||
|
html: string
|
||||||
|
}
|
||||||
|
export class SearchBox extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.disabled = true
|
||||||
|
this.html = /*html*/`
|
||||||
|
<form id="custom-navbar-search" autocomplete="off" target="_blank" method="get" action="https://search.bilibili.com/all">
|
||||||
|
<input type="text" placeholder="搜索" name="keyword">
|
||||||
|
<input type="hidden" name="from_source" value="banner_search">
|
||||||
|
<a style="display: none" target="_blank" class="recommended-target"></a>
|
||||||
|
<button type="submit" title="搜索" tabindex="-1">
|
||||||
|
<svg style="width:22px;height:22px" viewBox="0 0 24 24">
|
||||||
|
<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<div class="popup search-list" :class="{empty: items.length === 0}">
|
||||||
|
<div class="search-list-item" tabindex="0" v-for="(item, index) of items" v-html="item.html" :title="isHistory ? item.html : ''" @keydown.enter="submit(item.value)" @click.self="submit(item.value)" @keydown.shift.delete="deleteItem(item, index)" @keydown.down.prevent="nextItem(index)" @keydown.up.prevent="previousItem(index)"></div>
|
||||||
|
<div tabindex="0" v-if="items.length > 0 && isHistory" class="search-list-item clear-history" @click="clearSearchHistory()" @keydown.enter="clearSearchHistory()" @keydown.down.prevent="nextItem(items.length)" @keydown.up.prevent="previousItem(items.length)"><i class="mdi mdi-18px mdi-delete-sweep"></i>清除搜索历史</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
const form = await SpinQuery.select('#custom-navbar-search') as HTMLFormElement
|
||||||
|
const keywordInput = form.querySelector("input[name='keyword']") as HTMLInputElement
|
||||||
|
form.addEventListener('submit', e => {
|
||||||
|
if (keywordInput.value === '') {
|
||||||
|
if (!settings.hideTopSearch) {
|
||||||
|
(form.querySelector('.recommended-target') as HTMLElement).click()
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (/^av[\d]+$/.test(keywordInput.value)) {
|
||||||
|
window.open(`https://www.bilibili.com/${keywordInput.value}`)
|
||||||
|
e.preventDefault()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const historyItem = settings.searchHistory.find(item => item.keyword === keywordInput.value)
|
||||||
|
if (historyItem) {
|
||||||
|
historyItem.count++
|
||||||
|
historyItem.date = new Date().toJSON()
|
||||||
|
console.log(historyItem)
|
||||||
|
} else {
|
||||||
|
settings.searchHistory.unshift({
|
||||||
|
count: 1,
|
||||||
|
keyword: keywordInput.value,
|
||||||
|
date: new Date().toJSON(),
|
||||||
|
})
|
||||||
|
console.log({
|
||||||
|
count: 1,
|
||||||
|
keyword: keywordInput.value,
|
||||||
|
date: new Date().toJSON(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
settings.searchHistory = settings.searchHistory.slice(0, 10) // save history
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if (!settings.hideTopSearch) {
|
||||||
|
const json = await Ajax.getJson('https://api.bilibili.com/x/web-interface/search/default')
|
||||||
|
if (json.code === 0) {
|
||||||
|
keywordInput.setAttribute('placeholder', json.data.show_name)
|
||||||
|
let href
|
||||||
|
if (json.data.url !== '') {
|
||||||
|
href = json.data.url
|
||||||
|
}
|
||||||
|
else if (json.data.name.startsWith('av')) {
|
||||||
|
href = `https://www.bilibili.com/${json.data.name}`
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
href = `https://search.bilibili.com/all?keyword=${json.data.name}`
|
||||||
|
}
|
||||||
|
(form.querySelector('.recommended-target') as HTMLElement).setAttribute('href', href)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error('[自定义顶栏] 获取搜索推荐词失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const searchList = new Vue({
|
||||||
|
el: dq('.popup.search-list') as HTMLElement,
|
||||||
|
data: {
|
||||||
|
items: [] as SuggestItem[],
|
||||||
|
isHistory: true,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit(value: string) {
|
||||||
|
keywordInput.value = value
|
||||||
|
form.submit()
|
||||||
|
// submit method will not trigger submit event
|
||||||
|
// see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
|
||||||
|
raiseEvent(form, 'submit')
|
||||||
|
},
|
||||||
|
nextItem(index: number) {
|
||||||
|
const item = dq(`.custom-navbar .search-list-item:nth-child(${index + 2})`) as HTMLElement
|
||||||
|
if (item) {
|
||||||
|
item.focus()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
previousItem(index: number) {
|
||||||
|
const item = dq(`.custom-navbar .search-list-item:nth-child(${index})`) as HTMLElement
|
||||||
|
if (item) {
|
||||||
|
item.focus()
|
||||||
|
} else {
|
||||||
|
keywordInput.focus()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteItem(item: SuggestItem, index: number) {
|
||||||
|
settings.searchHistory.splice(settings.searchHistory.findIndex(it => it.keyword === item.value), 1)
|
||||||
|
settings.searchHistory = settings.searchHistory
|
||||||
|
this.items.splice(index, 1)
|
||||||
|
},
|
||||||
|
clearSearchHistory() {
|
||||||
|
settings.searchHistory = []
|
||||||
|
this.items = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
let lastQueuedRequest = ''
|
||||||
|
const updateSuggest = async () => {
|
||||||
|
const text = keywordInput.value
|
||||||
|
searchList.isHistory = text === ''
|
||||||
|
if (searchList.isHistory) {
|
||||||
|
searchList.items = settings.searchHistory
|
||||||
|
.sort((a, b) => {
|
||||||
|
const aDate = a.date ? new Date(a.date) : new Date(0)
|
||||||
|
const bDate = b.date ? new Date(b.date) : new Date(0)
|
||||||
|
return Number(bDate) - Number(aDate)
|
||||||
|
})
|
||||||
|
.map(item => {
|
||||||
|
return {
|
||||||
|
value: item.keyword,
|
||||||
|
html: item.keyword,
|
||||||
|
}
|
||||||
|
}).slice(0, 10)
|
||||||
|
} else {
|
||||||
|
const url = `https://s.search.bilibili.com/main/suggest?func=suggest&suggest_type=accurate&sub_type=tag&main_ver=v1&highlight=&userid=${getUID()}&bangumi_acc_num=1&special_acc_num=1&topic_acc_num=1&upuser_acc_num=3&tag_num=10&special_num=10&bangumi_num=10&upuser_num=3&term=${text}`
|
||||||
|
lastQueuedRequest = url
|
||||||
|
const json = await Ajax.getJson(url)
|
||||||
|
if (json.code !== 0 || lastQueuedRequest !== url) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const results = json.result.tag
|
||||||
|
if (results === undefined) {
|
||||||
|
searchList.items = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
searchList.items = results.map((item: any) => {
|
||||||
|
return {
|
||||||
|
value: item.value,
|
||||||
|
html: item.name.replace(/suggest_high_light/g, 'suggest-highlight')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateSuggest()
|
||||||
|
const debouncedSuggest = _.debounce(updateSuggest, 200)
|
||||||
|
let composing = false
|
||||||
|
keywordInput.addEventListener('compositionstart', () => composing = true)
|
||||||
|
keywordInput.addEventListener('compositionend', () => {
|
||||||
|
composing = false
|
||||||
|
raiseEvent(keywordInput, 'input')
|
||||||
|
})
|
||||||
|
keywordInput.addEventListener('input', () => {
|
||||||
|
if (!composing) {
|
||||||
|
debouncedSuggest()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
keywordInput.addEventListener('keydown', e => {
|
||||||
|
if (e.key === 'ArrowDown' && searchList.items.length > 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
(dq('.custom-navbar .search-list-item:first-child') as HTMLElement).focus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'search'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
SearchBox,
|
||||||
|
},
|
||||||
|
}
|
||||||
18
src/style/custom-navbar/simple/custom-navbar-simple-link.ts
Normal file
18
src/style/custom-navbar/simple/custom-navbar-simple-link.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export class SimpleLink extends NavbarComponent {
|
||||||
|
constructor(name: string, link: string, public linkName: string) {
|
||||||
|
super()
|
||||||
|
this.html = name
|
||||||
|
this.href = link
|
||||||
|
this.touch = false
|
||||||
|
this.active = document.URL.startsWith(link)
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return (this.linkName + 'Link') as keyof CustomNavbarOrders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
SimpleLink,
|
||||||
|
},
|
||||||
|
}
|
||||||
29
src/style/custom-navbar/simple/custom-navbar-upload.ts
Normal file
29
src/style/custom-navbar/simple/custom-navbar-upload.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export class Upload extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.href = 'https://member.bilibili.com/v2#/upload/video/frame'
|
||||||
|
this.html = /*html*/`
|
||||||
|
<svg style="width:16px;height:16px;padding:3px;box-sizing:content-box;" viewBox="0 0 785 886">
|
||||||
|
<path d="M582,374L582,566C582,585.333 576.167,600.833 564.5,612.5C552.833,624.167 537.333,630 518,630L262,630C242.667,630 227.167,624.167 215.5,612.5C203.833,600.833 198,585.333 198,566L198,374L32,374C22,374 14.1667,371.167 8.5,365.5C2.83333,359.833 0,352 0,342C0,338.667 1.16666,334.5 3.5,329.5C5.83333,324.5 8.66666,320 12,316L371,9C377.667,3.00006 385.167,6.10352e-005 393.5,0C401.833,6.10352e-005 409.333,3.00006 416,9L774,316C780,322.667 783.333,330.167 784,338.5C784.667,346.833 783.333,354.333 780,361L764,370C760,372.667 754.667,374 748,374ZM70,758L710,758C729.333,758 744.833,763.833 756.5,775.5C768.167,787.167 774,802.667 774,822C774,841.333 768.167,856.833 756.5,868.5C744.833,880.167 729.333,886 710,886L70,886C50.6667,886 35.1667,880.167 23.5,868.5C11.8333,856.833 6,841.333 6,822C6,802.667 11.8333,787.167 23.5,775.5C35.1667,763.833 50.6667,758 70,758Z" />
|
||||||
|
</svg>
|
||||||
|
<div id="upload-button">投稿</div>`
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<ul id="upload-actions">
|
||||||
|
<li><a target="_blank" href="https://member.bilibili.com/v2#/upload/text/apply">专栏投稿</a></li>
|
||||||
|
<li><a target="_blank" href="https://member.bilibili.com/v2#/upload/audio/">音频投稿</a></li>
|
||||||
|
<li><a target="_blank" href="https://member.bilibili.com/v2#/upload/video/frame">视频投稿</a></li>
|
||||||
|
<li><a target="_blank" href="https://member.bilibili.com/v2#/upload-manager/article">投稿管理</a></li>
|
||||||
|
<li><a target="_blank" href="https://member.bilibili.com/v2#/home">创作中心</a></li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'upload'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Upload,
|
||||||
|
},
|
||||||
|
}
|
||||||
220
src/style/custom-navbar/simple/custom-navbar-user-info.ts
Normal file
220
src/style/custom-navbar/simple/custom-navbar-user-info.ts
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
type PrivilegeType = 1 | 2
|
||||||
|
export class UserInfo extends NavbarComponent {
|
||||||
|
userInfo: any = {
|
||||||
|
mid: getUID(),
|
||||||
|
isLogin: Boolean(getUID()),
|
||||||
|
}
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.noPadding = true
|
||||||
|
this.href = 'https://space.bilibili.com'
|
||||||
|
this.html = /*html*/`
|
||||||
|
<div class="user-face-container">
|
||||||
|
<img src='${EmptyImageUrl}' class="user-face"></img>
|
||||||
|
<img src='${EmptyImageUrl}' class="user-pendant"></img>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<div class="user-info-panel">
|
||||||
|
<div v-if="isLogin" class="logged-in">
|
||||||
|
<a class="name" target="_blank" href="https://space.bilibili.com/">{{uname}}</a>
|
||||||
|
<a class="type" target="_blank" href="https://account.bilibili.com/account/big">{{userType}}</a>
|
||||||
|
<div class="privileges row" v-if="this.vipType === 2">
|
||||||
|
<div class="b-coin" :class="{received: privileges.bCoin.received}" @click="privilegeReceive(1)" :title="'有效期限: ' + privileges.bCoin.expire">
|
||||||
|
{{privileges.bCoin.received ? '已领取B币' : '领取B币'}}
|
||||||
|
</div>
|
||||||
|
<div class="coupons" :class="{received: privileges.coupons.received}" @click="privilegeReceive(2)" :title="'有效期限: ' + privileges.coupons.expire">
|
||||||
|
{{privileges.coupons.received ? '已领取优惠券' : '领取优惠券'}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-info row">
|
||||||
|
<a target="_blank" title="等级" href="https://account.bilibili.com/account/record"
|
||||||
|
class="level">
|
||||||
|
<i class="custom-navbar-iconfont-extended" :class="'custom-navbar-icon-lv' + level_info.current_level"></i>
|
||||||
|
</a>
|
||||||
|
<span class="level-progress-label">{{level_info.current_exp}} / {{level_info.next_exp}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="level-progress separator">
|
||||||
|
<div class="level-progress-thumb" :style="levelProgressStyle"></div>
|
||||||
|
</div>
|
||||||
|
<div class="items">
|
||||||
|
<a class="item" target="_blank" title="手机验证"
|
||||||
|
href="https://passport.bilibili.com/account/security#/bindphone">
|
||||||
|
<i class="custom-navbar-iconfont-new-home custom-navbar-icon-bind-phone"></i>
|
||||||
|
<i v-if="mobile_verified" class="custom-navbar-iconfont-new-home custom-navbar-icon-ok"></i>
|
||||||
|
<i v-else class="custom-navbar-iconfont-new-home custom-navbar-icon-cancel"></i>
|
||||||
|
</a>
|
||||||
|
<a class="item" target="_blank" title="邮箱验证"
|
||||||
|
href="https://passport.bilibili.com/account/security#/bindmail">
|
||||||
|
<i class="custom-navbar-iconfont-new-home custom-navbar-icon-bind-email"></i>
|
||||||
|
<i v-if="email_verified" class="custom-navbar-iconfont-new-home custom-navbar-icon-ok"></i>
|
||||||
|
<i v-else class="custom-navbar-iconfont-new-home custom-navbar-icon-cancel"></i>
|
||||||
|
</a>
|
||||||
|
<a class="item" target="_blank" href="https://account.bilibili.com/site/coin" title="硬币">
|
||||||
|
<i class="custom-navbar-iconfont-new-home custom-navbar-icon-coin"></i>
|
||||||
|
<span>{{money}}</span>
|
||||||
|
</a>
|
||||||
|
<a class="item" target="_blank" href="https://pay.bilibili.com/bb_balance.html" title="B币">
|
||||||
|
<i class="custom-navbar-iconfont-new-home custom-navbar-icon-b-coin"></i>
|
||||||
|
<span>{{wallet.bcoin_balance}}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="separator"></div>
|
||||||
|
<a class="operation" target="_blank" href="https://account.bilibili.com/account/home">
|
||||||
|
<i class="icon custom-navbar-icon-profile custom-navbar-iconfont-new-home"></i>
|
||||||
|
个人中心
|
||||||
|
</a>
|
||||||
|
<a class="operation" target="_blank" href="https://member.bilibili.com/v2#/upload-manager/article">
|
||||||
|
<i class="icon custom-navbar-icon-posts custom-navbar-iconfont-new-home"></i>
|
||||||
|
投稿管理
|
||||||
|
</a>
|
||||||
|
<a class="operation" target="_blank" href="https://pay.bilibili.com/">
|
||||||
|
<i class="icon custom-navbar-icon-wallet custom-navbar-iconfont-new-home"></i>
|
||||||
|
B币钱包
|
||||||
|
</a>
|
||||||
|
<a class="operation" target="_blank" href="https://link.bilibili.com/p/center/index">
|
||||||
|
<i class="icon custom-navbar-icon-live-center custom-navbar-iconfont-new-home"></i>
|
||||||
|
直播中心
|
||||||
|
</a>
|
||||||
|
<a class="operation" target="_blank" href="https://show.bilibili.com/orderlist">
|
||||||
|
<i class="icon custom-navbar-icon-order-center custom-navbar-iconfont-new-home"></i>
|
||||||
|
订单中心
|
||||||
|
</a>
|
||||||
|
<!-- <a class="operation" target="_blank" href="https://www.bilibili.com/v/cheese/mine">
|
||||||
|
<i class="icon custom-navbar-icon-course custom-navbar-iconfont-new-home"></i>
|
||||||
|
我的课程
|
||||||
|
</a> -->
|
||||||
|
<a class="logout grey-button" href="https://account.bilibili.com/login?act=exit">
|
||||||
|
退出登录
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div v-else class="not-logged-in">
|
||||||
|
<h1 class="welcome">欢迎来到 bilibili</h1>
|
||||||
|
<a href="https://passport.bilibili.com/register/phone.html" class="signup grey-button">注册</a>
|
||||||
|
<a href="https://passport.bilibili.com/login" class="login theme-button">登录</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
this.requestedPopup = true
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'userInfo'
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
const panel = await SpinQuery.select('.custom-navbar .user-info-panel') as HTMLElement
|
||||||
|
const face = await SpinQuery.select('.custom-navbar .user-face-container .user-face') as HTMLElement
|
||||||
|
const userInfoJson = await Ajax.getJsonWithCredentials('https://api.bilibili.com/x/web-interface/nav')
|
||||||
|
const userStatJson = await Ajax.getJsonWithCredentials('https://api.bilibili.com/x/web-interface/nav/stat')
|
||||||
|
Object.assign(this.userInfo, userInfoJson.data)
|
||||||
|
Object.assign(this.userInfo, userStatJson.data)
|
||||||
|
const vm = new Vue({
|
||||||
|
el: panel,
|
||||||
|
data: {
|
||||||
|
...this.userInfo,
|
||||||
|
privileges: {
|
||||||
|
bCoin: {
|
||||||
|
received: false,
|
||||||
|
expire: '',
|
||||||
|
},
|
||||||
|
coupons: {
|
||||||
|
received: false,
|
||||||
|
expire: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
userType() {
|
||||||
|
if (!this.isLogin) {
|
||||||
|
return '未登录'
|
||||||
|
}
|
||||||
|
if (this.level_info.current_level === 0) {
|
||||||
|
return '注册会员'
|
||||||
|
}
|
||||||
|
if (this.vipStatus === 1) {
|
||||||
|
if (this.vipType === 1) {
|
||||||
|
return this.vip_theme_type ? '小会员' : '大会员'
|
||||||
|
}
|
||||||
|
else if (this.vipType === 2) {
|
||||||
|
return this.vip_theme_type ? '年度小会员' : '年度大会员'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '正式会员'
|
||||||
|
},
|
||||||
|
levelProgressStyle() {
|
||||||
|
const progress = (this.level_info.current_exp - this.level_info.current_min) / (this.level_info.next_exp - this.level_info.current_min)
|
||||||
|
return {
|
||||||
|
transform: `scaleX(${progress})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async privilegeReceive(type: PrivilegeType) {
|
||||||
|
const typeMapping = {
|
||||||
|
1: 'bCoin',
|
||||||
|
2: 'coupons'
|
||||||
|
}
|
||||||
|
if (this.privileges[typeMapping[type]].received) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.privileges[typeMapping[type]].received = true
|
||||||
|
const csrf = getCsrf()
|
||||||
|
const result = await (await fetch('https://api.bilibili.com/x/vip/privilege/receive',
|
||||||
|
{
|
||||||
|
credentials: 'include',
|
||||||
|
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
||||||
|
body: `type=${type}&csrf=${csrf}`,
|
||||||
|
method: 'POST'
|
||||||
|
})).json()
|
||||||
|
console.log(result)
|
||||||
|
if (result.code === 0) {
|
||||||
|
if (typeMapping[type] === 'bCoin') {
|
||||||
|
this.wallet.bcoin_balance += 5
|
||||||
|
}
|
||||||
|
} else if (result.code === 69801) { // 已领过
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
this.privileges[typeMapping[type]].received = false
|
||||||
|
logError(result.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (this.userInfo.isLogin) {
|
||||||
|
const faceUrl = this.userInfo.face.replace('http', 'https')
|
||||||
|
const noFaceUrl = 'static.hdslb.com/images/member/noface.gif'
|
||||||
|
if (!faceUrl.includes(noFaceUrl)) { // 没上传过头像的不做缩放
|
||||||
|
const faceBaseSize = 68
|
||||||
|
face.setAttribute('srcset', getDpiSourceSet(faceUrl, faceBaseSize))
|
||||||
|
} else {
|
||||||
|
face.setAttribute('src', noFaceUrl)
|
||||||
|
}
|
||||||
|
if (this.userInfo.pendant.image) {
|
||||||
|
const pendant = await SpinQuery.select('.custom-navbar .user-face-container .user-pendant') as HTMLElement
|
||||||
|
const pendantUrl = this.userInfo.pendant.image.replace('http', 'https')
|
||||||
|
const pendantBaseSize = 116
|
||||||
|
pendant.setAttribute('srcset', getDpiSourceSet(pendantUrl, pendantBaseSize, 'png'))
|
||||||
|
}
|
||||||
|
if (this.userInfo.vipType === 2) { // 年度大会员权益
|
||||||
|
const privileges = await Ajax.getJsonWithCredentials('https://api.bilibili.com/x/vip/privilege/my')
|
||||||
|
if (privileges.code === 0) {
|
||||||
|
const bCoin = privileges.data.list.find((it: { type: PrivilegeType }) => it.type === 1)
|
||||||
|
vm.privileges.bCoin.received = bCoin.state === 1
|
||||||
|
vm.privileges.bCoin.expire = new Date(bCoin.expire_time * 1000).toLocaleDateString()
|
||||||
|
const coupons = privileges.data.list.find((it: { type: PrivilegeType }) => it.type === 2)
|
||||||
|
vm.privileges.coupons.received = coupons.state === 1
|
||||||
|
vm.privileges.coupons.expire = new Date(coupons.expire_time * 1000).toLocaleDateString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
face.setAttribute('src', 'https://static.hdslb.com/images/akari.jpg')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
UserInfo,
|
||||||
|
},
|
||||||
|
}
|
||||||
125
src/style/custom-navbar/simple/custom-navbar-video-list.ts
Normal file
125
src/style/custom-navbar/simple/custom-navbar-video-list.ts
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
interface VideoListConfig {
|
||||||
|
mainUrl: string
|
||||||
|
name: string
|
||||||
|
apiUrl: string
|
||||||
|
listName: string
|
||||||
|
listMap: (json: any) => string[]
|
||||||
|
}
|
||||||
|
class VideoList extends NavbarComponent {
|
||||||
|
listName: string
|
||||||
|
constructor({ mainUrl, name, apiUrl, listName, listMap }: VideoListConfig) {
|
||||||
|
super()
|
||||||
|
this.href = mainUrl
|
||||||
|
this.listName = listName
|
||||||
|
this.html = name
|
||||||
|
this.noPadding = true
|
||||||
|
this.requestedPopup = false
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<ol class="video-list ${listName}">
|
||||||
|
<li class="loading">加载中...</li>
|
||||||
|
</ol>
|
||||||
|
`
|
||||||
|
this.initialPopup = async () => {
|
||||||
|
if (!listMap) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const videoListElement = await SpinQuery.select(`.video-list.${listName}`)
|
||||||
|
if (videoListElement === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const json = await Ajax.getJsonWithCredentials(apiUrl)
|
||||||
|
let videoList = ''
|
||||||
|
if (json.code !== 0) {
|
||||||
|
logError(`加载${name}信息失败. 错误码: ${json.code} ${json.message}`)
|
||||||
|
} else {
|
||||||
|
videoList = listMap(json).join("")
|
||||||
|
}
|
||||||
|
videoListElement.insertAdjacentHTML('beforeend', videoList + /*html*/`
|
||||||
|
<li class="more"><a target="_blank" href="${mainUrl}">查看更多</a></li>
|
||||||
|
`)
|
||||||
|
videoListElement.classList.add('loaded')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return (this.listName + 'List') as keyof CustomNavbarOrders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class FavoritesList extends VideoList {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
name: "收藏",
|
||||||
|
mainUrl: `https://space.bilibili.com/${getUID()}/favlist`,
|
||||||
|
apiUrl: "https://api.bilibili.com/medialist/gateway/coll/resource/recent",
|
||||||
|
listName: "favorites",
|
||||||
|
listMap: json => {
|
||||||
|
if (!json.data || json.data.length === 0) {
|
||||||
|
return [/*html*/`<li class="loading empty">空空如也哦 = ̄ω ̄=</li>`]
|
||||||
|
}
|
||||||
|
return json.data.map((item: any) => {
|
||||||
|
return /*html*/`
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="https://www.bilibili.com/video/av${item.id}">${item.title}</a>
|
||||||
|
</li>`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.active = document.URL.replace(/\?.*$/, "") === `https://space.bilibili.com/${getUID()}/favlist`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class HistoryList extends VideoList {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
name: "历史",
|
||||||
|
mainUrl: "https://www.bilibili.com/account/history",
|
||||||
|
apiUrl: "https://api.bilibili.com/x/v2/history?pn=1&ps=6",
|
||||||
|
listName: "history",
|
||||||
|
listMap: json => {
|
||||||
|
if (!json.data || json.data.length === 0) {
|
||||||
|
return [/*html*/`<li class="loading empty">空空如也哦 = ̄ω ̄=</li>`]
|
||||||
|
}
|
||||||
|
return json.data.map((item: any) => {
|
||||||
|
let parameter = []
|
||||||
|
let description = ""
|
||||||
|
const page = item.page ? item.page.page : 1
|
||||||
|
let progress = item.progress >= 0 ? item.progress / item.duration : 1
|
||||||
|
if (isNaN(progress)) {
|
||||||
|
progress = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page !== 1) {
|
||||||
|
parameter.push(`p=${page}`)
|
||||||
|
description += `看到第${page}话`
|
||||||
|
}
|
||||||
|
if (item.progress > 0 && item.progress < item.duration) {
|
||||||
|
parameter.push(`t=${item.progress}`)
|
||||||
|
description += ` ${Math.floor(progress * 100)}%`
|
||||||
|
}
|
||||||
|
else if (item.progress === 0) {
|
||||||
|
description += ` 刚开始看`
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
description += " 100%"
|
||||||
|
}
|
||||||
|
return /*html*/`
|
||||||
|
<li class="history-item">
|
||||||
|
<a target="_blank" href="https://www.bilibili.com/video/av${item.aid}?${parameter.join("&")}">
|
||||||
|
<span class="title">${item.title}</span>
|
||||||
|
<span class="description">${description}</span>
|
||||||
|
<div class="progress background">
|
||||||
|
<div class="progress foreground" style="--progress: ${progress * 100}%"></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.active = document.URL.replace(/\?.*$/, "") === "https://www.bilibili.com/account/history"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
FavoritesList,
|
||||||
|
HistoryList,
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
|
export class Subscriptions extends NavbarComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.noPadding = true
|
||||||
|
const uid = getUID()
|
||||||
|
this.href = `https://space.bilibili.com/${uid}/bangumi`
|
||||||
|
this.html = '订阅'
|
||||||
|
this.active = [`https://space.bilibili.com/${uid}/bangumi`, `https://space.bilibili.com/${uid}/cinema`, `https://space.bilibili.com/${uid}/subs`].includes(document.URL.replace(/\?.*$/, ""))
|
||||||
|
this.popupHtml = /*html*/`
|
||||||
|
<div class="subscriptions">
|
||||||
|
<ul class="subscriptions-tabs">
|
||||||
|
<li class="tab" :class="{selected: bangumi}" @click="bangumi = true">追番</li>
|
||||||
|
<li class="tab" :class="{selected: !bangumi}" @click="bangumi = false">追剧</li>
|
||||||
|
<div class="tab-placeholder"></div>
|
||||||
|
<a class="view-all" target="_blank" :href="'https://space.bilibili.com/${uid}/' + (bangumi ? 'bangumi' : 'cinema')">
|
||||||
|
查看更多
|
||||||
|
<i class="mdi mdi-dots-horizontal"></i>
|
||||||
|
</a>
|
||||||
|
</ul>
|
||||||
|
<div class="content">
|
||||||
|
<transition name="subscriptions-content" mode="out-in">
|
||||||
|
<bangumi-subscriptions v-if="bangumi" type="bangumi" :key="'bangumi'"></bangumi-subscriptions>
|
||||||
|
<bangumi-subscriptions v-else type="cinema" :key="'cinema'"></bangumi-subscriptions>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
this.initialPopup = () => { this.init() }
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
new Vue({
|
||||||
|
el: await SpinQuery.select('.custom-navbar .subscriptions') as HTMLElement,
|
||||||
|
data: {
|
||||||
|
bangumi: true,
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'bangumi-subscriptions': {
|
||||||
|
props: ['type'],
|
||||||
|
components: {
|
||||||
|
'dpi-img': () => import('../dpi-img.vue'),
|
||||||
|
},
|
||||||
|
template: /*html*/`
|
||||||
|
<div class="bangumi-subscriptions" :class="{center: loading || !loading && cards.length === 0}">
|
||||||
|
<div v-if="loading" class="loading">
|
||||||
|
<i class="mdi mdi-18px mdi-loading mdi-spin"></i>
|
||||||
|
加载中...
|
||||||
|
</div>
|
||||||
|
<div v-if="!loading && cards.length === 0" class="empty">空空如也哦 = ̄ω ̄=</div>
|
||||||
|
<a v-if="!loading" v-for="card of cards" :key="card.id" :href="card.playUrl" target="_blank" class="bangumi-subscriptions-card">
|
||||||
|
<dpi-img class="cover" :src="card.coverUrl" :size="{height: 64}"></dpi-img>
|
||||||
|
<div class="card-info">
|
||||||
|
<h1 class="title" :title="card.title">{{card.title}}</h1>
|
||||||
|
<div class="progress-row">
|
||||||
|
<div v-if="card.progress" class="progress" :title="card.progress + ' | ' + card.latest">{{card.progress}} | {{card.latest}}</div>
|
||||||
|
<div v-else class="progress" :title="card.latest">{{card.latest}}</div>
|
||||||
|
<a class="info" :href="card.mediaUrl" target="_blank" title="详细信息">
|
||||||
|
<i class="mdi mdi-information-outline"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
cards: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
try {
|
||||||
|
const json = await Ajax.getJsonWithCredentials(`https://api.bilibili.com/x/space/bangumi/follow/list?type=${this.type !== 'bangumi' ? '2' : '1'}&pn=1&ps=16&vmid=${getUID()}`)
|
||||||
|
if (json.code !== 0) {
|
||||||
|
logError(`加载订阅信息失败: ${json.message}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.cards = json.data.list.map((item: any) => {
|
||||||
|
return {
|
||||||
|
title: item.title,
|
||||||
|
coverUrl: item.square_cover.replace('http:', 'https:'),
|
||||||
|
latest: item.new_ep.index_show,
|
||||||
|
progress: item.progress,
|
||||||
|
id: item.season_id,
|
||||||
|
playUrl: `https://www.bilibili.com/bangumi/play/ss${item.season_id}`,
|
||||||
|
mediaUrl: `https://www.bilibili.com/bangumi/media/md${item.media_id}`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
get name(): keyof CustomNavbarOrders {
|
||||||
|
return 'bangumi'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
export: {
|
||||||
|
Subscriptions,
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { NavbarComponent } from './custom-navbar-component'
|
import { NavbarComponent } from '../custom-navbar-component'
|
||||||
interface WatchlaterCard {
|
interface WatchlaterCard {
|
||||||
aid: number
|
aid: number
|
||||||
href: string
|
href: string
|
||||||
@ -98,7 +98,7 @@ export class WatchlaterList extends NavbarComponent {
|
|||||||
methods: {
|
methods: {
|
||||||
...Vuex.mapActions(['toggleWatchlater']),
|
...Vuex.mapActions(['toggleWatchlater']),
|
||||||
async updateList() {
|
async updateList() {
|
||||||
const { getWatchlaterList } = await import('../../video/watchlater-api')
|
const { getWatchlaterList } = await import('../../../video/watchlater-api')
|
||||||
const rawList = await getWatchlaterList(true)
|
const rawList = await getWatchlaterList(true)
|
||||||
if (!rawList) {
|
if (!rawList) {
|
||||||
this.cards = []
|
this.cards = []
|
||||||
Loading…
Reference in New Issue
Block a user