mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Merge branch 'preview-fixes' into preview-features
This commit is contained in:
commit
fba8849f46
@ -30,6 +30,9 @@ https://afdian.com/a/the1812?tab=sponsor
|
|||||||
|
|
||||||
| 时间 | 用户名 | 单号后4位 | 金额 |
|
| 时间 | 用户名 | 单号后4位 | 金额 |
|
||||||
| ------------------- | --------------------- | --------- | ------- |
|
| ------------------- | --------------------- | --------- | ------- |
|
||||||
|
| 2025.07.12 16:44:24 | 爱音allin | 3957 | ¥5.00 |
|
||||||
|
| 2025.06.29 10:53:44 | f*x | 9352 | ¥10.00 |
|
||||||
|
| 2025.06.10 01:22:23 | *匆 | 5332 | ¥5.00 |
|
||||||
| 2025.05.21 19:55:02 | mobmaster69 | 7644 | ¥5.00 |
|
| 2025.05.21 19:55:02 | mobmaster69 | 7644 | ¥5.00 |
|
||||||
| 2025.05.20 02:38:45 | Duane | 3937 | ¥5.00 |
|
| 2025.05.20 02:38:45 | Duane | 3937 | ¥5.00 |
|
||||||
| 2025.05.15 22:12:22 | 匿名 | 3901 | ¥23.33 |
|
| 2025.05.15 22:12:22 | 匿名 | 3901 | ¥23.33 |
|
||||||
|
|||||||
@ -675,7 +675,7 @@
|
|||||||
"type": "component",
|
"type": "component",
|
||||||
"name": "subscribeTimeShow",
|
"name": "subscribeTimeShow",
|
||||||
"displayName": "关注时间显示",
|
"displayName": "关注时间显示",
|
||||||
"description": "by [@Light_Quanta](https://github.com/LightQuanta)\n\n在粉丝/关注列表显示关注的具体时间",
|
"description": "by [@CNOCM](https://github.com/CNOCM)\n\n在粉丝/关注列表及用户主页显示关注的具体时间。",
|
||||||
"fullRelativePath": "../../registry/dist/components/utils/subscribe-time-show.js",
|
"fullRelativePath": "../../registry/dist/components/utils/subscribe-time-show.js",
|
||||||
"fullAbsolutePath": "registry/dist/components/utils/subscribe-time-show.js"
|
"fullAbsolutePath": "registry/dist/components/utils/subscribe-time-show.js"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -946,9 +946,9 @@ by [@Light_Quanta](https://github.com/LightQuanta)
|
|||||||
|
|
||||||
**GitHub:** [`Stable`](https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/registry/dist/components/utils/subscribe-time-show.js) / [`Preview`](https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/registry/dist/components/utils/subscribe-time-show.js)
|
**GitHub:** [`Stable`](https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/registry/dist/components/utils/subscribe-time-show.js) / [`Preview`](https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/registry/dist/components/utils/subscribe-time-show.js)
|
||||||
|
|
||||||
by [@Light_Quanta](https://github.com/LightQuanta)
|
by [@CNOCM](https://github.com/CNOCM)
|
||||||
|
|
||||||
在粉丝/关注列表显示关注的具体时间
|
在粉丝/关注列表及用户主页显示关注的具体时间。
|
||||||
|
|
||||||
### [网址参数清理](../../registry/dist/components/utils/url-params-clean.js)
|
### [网址参数清理](../../registry/dist/components/utils/url-params-clean.js)
|
||||||
`urlParamsClean`
|
`urlParamsClean`
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import { defineComponentMetadata } from '@/components/define'
|
import { defineComponentMetadata } from '@/components/define'
|
||||||
import { useScopedConsole } from '@/core/utils/log'
|
import { useScopedConsole } from '@/core/utils/log'
|
||||||
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
||||||
|
import { select } from '@/core/spin-query'
|
||||||
|
import { allMutations } from '@/core/observer'
|
||||||
|
import { getUserInfo } from '@/core/user-info'
|
||||||
|
|
||||||
const displayName = '关注时间显示'
|
const displayName = '关注时间显示'
|
||||||
const console = useScopedConsole(displayName)
|
const console = useScopedConsole(displayName)
|
||||||
@ -22,20 +25,16 @@ type FollowTimeInfo = {
|
|||||||
const midMap: Record<number, FollowTimeInfo> = {}
|
const midMap: Record<number, FollowTimeInfo> = {}
|
||||||
|
|
||||||
const insertFollowTimeToCard = (mid: number, dateStr: string, label: string) => {
|
const insertFollowTimeToCard = (mid: number, dateStr: string, label: string) => {
|
||||||
const anchor = document.querySelector<HTMLAnchorElement>(
|
const anchor = dq(`${SELECTORS.relationCardAnchor}[href*="/${mid}"]`)
|
||||||
`${SELECTORS.relationCardAnchor}[href*="/${mid}"]`,
|
|
||||||
)
|
|
||||||
const card = anchor?.closest(SELECTORS.relationCardContainer)
|
const card = anchor?.closest(SELECTORS.relationCardContainer)
|
||||||
if (!card) {
|
if (!card || card.querySelector(`.${SELECTORS.relationCardTimeClass}`)) {
|
||||||
return
|
|
||||||
}
|
|
||||||
if (card.querySelector(`.${SELECTORS.relationCardTimeClass}`)) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const div = document.createElement('div')
|
const div = document.createElement('div')
|
||||||
div.className = SELECTORS.relationCardTimeClass
|
div.className = SELECTORS.relationCardTimeClass
|
||||||
div.textContent = `${label}:${dateStr}`
|
div.textContent = `${label}:${dateStr}`
|
||||||
|
div.dataset.mid = mid.toString()
|
||||||
|
|
||||||
const sign = card.querySelector(SELECTORS.relationCardSign)
|
const sign = card.querySelector(SELECTORS.relationCardSign)
|
||||||
if (sign?.parentNode) {
|
if (sign?.parentNode) {
|
||||||
@ -43,24 +42,24 @@ const insertFollowTimeToCard = (mid: number, dateStr: string, label: string) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let fetchWrapped = false
|
const updateCards = (() => {
|
||||||
let pendingUpdate = false
|
let scheduled = false
|
||||||
|
return () => {
|
||||||
const updateCards = () => {
|
if (scheduled) {
|
||||||
if (pendingUpdate) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pendingUpdate = true
|
scheduled = true
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
pendingUpdate = false
|
scheduled = false
|
||||||
const mids = Array.from(
|
dqa(SELECTORS.relationCardAnchor).forEach(el => {
|
||||||
document.querySelectorAll<HTMLAnchorElement>(SELECTORS.relationCardAnchor),
|
const match = (el as HTMLAnchorElement).href.match(/\/(\d+)/)
|
||||||
)
|
if (!match) {
|
||||||
.map(el => el.href.match(/\/(\d+)/)?.[1])
|
return
|
||||||
.filter(Boolean)
|
}
|
||||||
.map(Number)
|
const mid = Number(match[1])
|
||||||
|
if (Number.isNaN(mid)) {
|
||||||
mids.forEach(mid => {
|
return
|
||||||
|
}
|
||||||
const data = midMap[mid]
|
const data = midMap[mid]
|
||||||
if (data) {
|
if (data) {
|
||||||
const dateStr = new Date(data.mtime * 1000).toLocaleString()
|
const dateStr = new Date(data.mtime * 1000).toLocaleString()
|
||||||
@ -69,31 +68,11 @@ const updateCards = () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
})()
|
||||||
const waitForProfileContainer = () =>
|
|
||||||
new Promise<Element>(resolve => {
|
|
||||||
const check = () => document.querySelector(SELECTORS.profileFollowContainer)
|
|
||||||
let container = check()
|
|
||||||
if (container) {
|
|
||||||
resolve(container)
|
|
||||||
} else {
|
|
||||||
const observer = new MutationObserver(() => {
|
|
||||||
container = check()
|
|
||||||
if (container) {
|
|
||||||
observer.disconnect()
|
|
||||||
resolve(container)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
observer.observe(document.body, { childList: true, subtree: true })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const insertSubscribeTime = (followTimeStr: string) => {
|
const insertSubscribeTime = (followTimeStr: string) => {
|
||||||
const container = document.querySelector(SELECTORS.profileFollowContainer)
|
const container = dq(SELECTORS.profileFollowContainer)
|
||||||
if (!container) {
|
if (!container || container.querySelector(`.${SELECTORS.profileTextClass}`)) {
|
||||||
return
|
|
||||||
}
|
|
||||||
if (container.querySelector(`.${SELECTORS.profileTextClass}`)) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,25 +86,22 @@ const insertSubscribeTime = (followTimeStr: string) => {
|
|||||||
container.appendChild(infoEl)
|
container.appendChild(infoEl)
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = async () => {
|
if (!(unsafeWindow as any).subscribeTimeHooked) {
|
||||||
try {
|
;(unsafeWindow as any).subscribeTimeHooked = true
|
||||||
const { addImportantStyle } = await import('@/core/style')
|
|
||||||
const { default: style } = await import('./subscribe-time.scss')
|
|
||||||
addImportantStyle(style, 'subscribe-time-style')
|
|
||||||
} catch (e) {
|
|
||||||
console.error('样式加载失败:', e)
|
|
||||||
}
|
|
||||||
|
|
||||||
new MutationObserver(updateCards).observe(document.body, { childList: true, subtree: true })
|
|
||||||
|
|
||||||
if (!fetchWrapped) {
|
|
||||||
fetchWrapped = true
|
|
||||||
const originalFetch = unsafeWindow.fetch
|
const originalFetch = unsafeWindow.fetch
|
||||||
unsafeWindow.fetch = new Proxy(originalFetch, {
|
unsafeWindow.fetch = new Proxy(originalFetch, {
|
||||||
apply(target, thisArg, args) {
|
apply(target, thisArg, args) {
|
||||||
const url = typeof args[0] === 'string' ? args[0] : args[0].url
|
const url = typeof args[0] === 'string' ? args[0] : args[0].url
|
||||||
if (url.includes('/x/relation/fans') || url.includes('/x/relation/followings')) {
|
const urlObj = new URL(url, location.origin)
|
||||||
return target.apply(thisArg, args).then(res => {
|
|
||||||
|
if (
|
||||||
|
urlObj.hostname === 'api.bilibili.com' &&
|
||||||
|
(urlObj.pathname.includes('/x/relation/fans') ||
|
||||||
|
urlObj.pathname.includes('/x/relation/followings'))
|
||||||
|
) {
|
||||||
|
return target
|
||||||
|
.apply(thisArg, args)
|
||||||
|
.then(res => {
|
||||||
res
|
res
|
||||||
.clone()
|
.clone()
|
||||||
.json()
|
.json()
|
||||||
@ -137,54 +113,63 @@ const entry = async () => {
|
|||||||
}
|
}
|
||||||
list.forEach(user => {
|
list.forEach(user => {
|
||||||
if (typeof user.mid === 'number' && typeof user.mtime === 'number') {
|
if (typeof user.mid === 'number' && typeof user.mtime === 'number') {
|
||||||
const label = url.includes('/x/relation/fans')
|
const label = url.includes('/fans') ? 'Ta 关注你的时间' : '你关注 Ta 的时间'
|
||||||
? 'Ta 关注你的时间'
|
|
||||||
: '你关注 Ta 的时间'
|
|
||||||
midMap[user.mid] = { mtime: user.mtime, label }
|
midMap[user.mid] = { mtime: user.mtime, label }
|
||||||
insertFollowTimeToCard(
|
const dateStr = new Date(user.mtime * 1000).toLocaleString()
|
||||||
user.mid,
|
insertFollowTimeToCard(user.mid, dateStr, label)
|
||||||
new Date(user.mtime * 1000).toLocaleString(),
|
|
||||||
label,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(err => console.warn('JSON 解析失败:', err))
|
.catch(err => {
|
||||||
|
console.warn('JSON 解析失败:', err)
|
||||||
|
})
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.warn('fetch 请求失败:', err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return target.apply(thisArg, args)
|
return target.apply(thisArg, args)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const entry = async () => {
|
||||||
|
try {
|
||||||
|
const { addImportantStyle } = await import('@/core/style')
|
||||||
|
const { default: style } = await import('./subscribe-time.scss')
|
||||||
|
addImportantStyle(style, 'subscribe-time-style')
|
||||||
|
} catch (e) {
|
||||||
|
console.error('样式加载失败:', e)
|
||||||
|
}
|
||||||
|
|
||||||
|
allMutations(updateCards)
|
||||||
|
|
||||||
|
const userMid = (await getUserInfo()).mid
|
||||||
const match = location.href.match(/space\.bilibili\.com\/(\d+)/)
|
const match = location.href.match(/space\.bilibili\.com\/(\d+)/)
|
||||||
if (!match) {
|
if (!match) {
|
||||||
console.warn('无法提取 mid')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const mid = Number(match[1])
|
const mid = Number(match[1])
|
||||||
|
if (mid === userMid) {
|
||||||
|
console.log('当前为本人空间,跳过关注时间显示')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const info = await bilibiliApi(
|
const info = await bilibiliApi(
|
||||||
getJsonWithCredentials(`https://api.bilibili.com/x/web-interface/relation?mid=${mid}`),
|
getJsonWithCredentials(`https://api.bilibili.com/x/web-interface/relation?mid=${mid}`),
|
||||||
)
|
)
|
||||||
if (!info?.relation) {
|
|
||||||
console.warn('未获取到 relation 信息')
|
const mtime = info?.relation?.mtime
|
||||||
return
|
if (!mtime) {
|
||||||
}
|
|
||||||
if (!info.relation.mtime) {
|
|
||||||
console.log('当前未关注或关注时间无效')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
await select(SELECTORS.profileFollowContainer)
|
||||||
await waitForProfileContainer()
|
insertSubscribeTime(new Date(mtime * 1000).toLocaleString())
|
||||||
} catch (e) {
|
|
||||||
console.warn('等待关注容器超时,跳过插入关注时间')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
insertSubscribeTime(new Date(info.relation.mtime * 1000).toLocaleString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const component = defineComponentMetadata({
|
export const component = defineComponentMetadata({
|
||||||
@ -200,5 +185,7 @@ export const component = defineComponentMetadata({
|
|||||||
/https:\/\/space\.bilibili\.com\/\d+/,
|
/https:\/\/space\.bilibili\.com\/\d+/,
|
||||||
],
|
],
|
||||||
entry,
|
entry,
|
||||||
description: { 'zh-CN': '在粉丝/关注列表及用户主页显示关注的具体时间。' },
|
description: {
|
||||||
|
'zh-CN': '在粉丝/关注列表及用户主页显示关注的具体时间。',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "2.10.2",
|
"version": "2.10.3",
|
||||||
"author": "Grant Howard, Coulomb-G",
|
"author": "Grant Howard, Coulomb-G",
|
||||||
"copyright": "[year], Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G)",
|
"copyright": "[year], Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user