mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
264 lines
7.1 KiB
Vue
264 lines
7.1 KiB
Vue
<template>
|
|
<div class="multiple-widgets">
|
|
<VPopup
|
|
ref="medalPopup"
|
|
v-model:open="medalOpen"
|
|
class="badge-popup widgets-popup medal"
|
|
:trigger-element="medalButton"
|
|
>
|
|
<ul>
|
|
<li
|
|
v-for="medal of medalList"
|
|
:key="medal.id"
|
|
:data-id="medal.id"
|
|
:class="{ active: medal.isActive, gray: grayEffect && !medal.isLighted }"
|
|
:title="medal.upName"
|
|
@click="toggleBadge(medal, medalList)"
|
|
>
|
|
<div class="fans-medal-item" :class="['level-' + medal.level]">
|
|
<span class="label">{{ medal.name }}</span>
|
|
<span class="level">{{ medal.level }}</span>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</VPopup>
|
|
<DefaultWidget ref="medalButton" icon="mdi-medal" @click="medalOpen = !medalOpen">
|
|
<span>更换勋章</span>
|
|
</DefaultWidget>
|
|
|
|
<VPopup
|
|
ref="titlePopup"
|
|
v-model:open="titleOpen"
|
|
class="badge-popup widgets-popup title"
|
|
:trigger-element="titleButton"
|
|
>
|
|
<ul>
|
|
<li
|
|
v-for="title of titleList"
|
|
:key="title.id"
|
|
:data-id="title.id"
|
|
:class="{ active: title.isActive }"
|
|
@click="toggleBadge(title, titleList)"
|
|
>
|
|
<img :src="title.imageUrl" class="title-image" />
|
|
</li>
|
|
</ul>
|
|
</VPopup>
|
|
<DefaultWidget ref="titleButton" icon="mdi-script-outline" @click="titleOpen = !titleOpen">
|
|
<span>更换头衔</span>
|
|
</DefaultWidget>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, ref } from 'vue'
|
|
import type { Ref } from 'vue'
|
|
import { addComponentListener, getComponentSettings } from '@/core/settings'
|
|
import { descendingSort } from '@/core/utils/sort'
|
|
import { DefaultWidget, VPopup } from '@/ui'
|
|
|
|
import type { Badge } from './badge'
|
|
import { getMedalList, getTitleList, Medal, Title } from './badge'
|
|
import type { Options } from './index'
|
|
|
|
const { options } = getComponentSettings<Options>('badgeHelper')
|
|
export default defineComponent({
|
|
components: {
|
|
DefaultWidget,
|
|
VPopup,
|
|
},
|
|
setup: () => ({
|
|
medalPopup: ref(null) as Ref<InstanceType<typeof VPopup> | null>,
|
|
titlePopup: ref(null) as Ref<InstanceType<typeof VPopup> | null>,
|
|
medalButton: ref(null) as Ref<InstanceType<typeof DefaultWidget> | null>,
|
|
titleButton: ref(null) as Ref<InstanceType<typeof DefaultWidget> | null>,
|
|
}),
|
|
data() {
|
|
return {
|
|
medalList: [] as Medal[],
|
|
titleList: [] as Title[],
|
|
medalOpen: false,
|
|
titleOpen: false,
|
|
grayEffect: true,
|
|
}
|
|
},
|
|
async mounted() {
|
|
addComponentListener(
|
|
'badgeHelper.grayEffect',
|
|
(enable: boolean) => {
|
|
this.grayEffect = enable
|
|
},
|
|
true,
|
|
)
|
|
const init = async () => {
|
|
const medal = this.loadMedalList()
|
|
await Title.getImageMap()
|
|
const title = this.loadTitleList()
|
|
return Promise.all([medal, title])
|
|
}
|
|
await init()
|
|
this.updateColumnsCount()
|
|
},
|
|
methods: {
|
|
updateColumnsCount() {
|
|
const maxColumnCount = 15
|
|
const columnLength = 18
|
|
const element = this.$el as HTMLElement
|
|
const medalColumns = Math.min(Math.ceil(this.medalList.length / columnLength), maxColumnCount)
|
|
element.style.setProperty('--medal-columns', medalColumns.toString())
|
|
const titleColumns = Math.min(Math.ceil(this.titleList.length / columnLength), maxColumnCount)
|
|
element.style.setProperty('--title-columns', titleColumns.toString())
|
|
},
|
|
async loadMedalList() {
|
|
this.medalList = (await getMedalList())
|
|
.sort(descendingSort(it => it.level))
|
|
.slice(0, options.maxBadgeCount)
|
|
},
|
|
async loadTitleList() {
|
|
this.titleList = (await getTitleList()).slice(0, options.maxBadgeCount)
|
|
},
|
|
async toggleBadge(badge: Badge, list: Badge[]) {
|
|
console.log(badge)
|
|
if (badge.isActive) {
|
|
badge.isActive = false
|
|
await badge.deactivate()
|
|
} else {
|
|
const activeBadge = list.find(b => b.isActive)
|
|
if (activeBadge) {
|
|
activeBadge.isActive = false
|
|
}
|
|
badge.isActive = true
|
|
await badge.activate()
|
|
if (badge instanceof Medal) {
|
|
options.defaultMedalID = badge.id
|
|
}
|
|
}
|
|
if (badge instanceof Medal) {
|
|
await this.loadMedalList()
|
|
} else if (badge instanceof Title) {
|
|
await this.loadTitleList()
|
|
}
|
|
},
|
|
},
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import 'common';
|
|
.badge-popup {
|
|
top: 50%;
|
|
left: calc(100% + 8px);
|
|
transform: scale(0.9) translateY(-50%);
|
|
transform-origin: left;
|
|
padding: 4px;
|
|
max-height: calc(100vh - 150px);
|
|
@include card();
|
|
@include no-scrollbar();
|
|
@include round-corner(4px);
|
|
&.open {
|
|
transform: scale(1) translateY(-50%);
|
|
}
|
|
body.settings-panel-dock-right & {
|
|
right: calc(100% + 8px);
|
|
left: unset;
|
|
transform-origin: right;
|
|
}
|
|
&,
|
|
& * {
|
|
transition: 0.2s ease-out;
|
|
}
|
|
ul {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
li {
|
|
@include round-corner(4px);
|
|
cursor: pointer;
|
|
padding: 6px 8px;
|
|
display: flex;
|
|
justify-content: center;
|
|
&:hover {
|
|
background-color: #8882;
|
|
}
|
|
&.active {
|
|
box-shadow: 0 0 0px 1px var(--theme-color), 0 0 0px 3px var(--theme-color-20);
|
|
}
|
|
&.gray:not(:hover) {
|
|
filter: grayscale(1);
|
|
}
|
|
.title-image {
|
|
display: inline-block;
|
|
vertical-align: middle;
|
|
height: 20px;
|
|
}
|
|
$rankColors: (
|
|
0: #48b6a5,
|
|
1: #5896de,
|
|
2: #a068f1,
|
|
3: #ff86b2,
|
|
4: #f6be18,
|
|
);
|
|
.fans-medal-item {
|
|
// display: inline-block;
|
|
display: flex !important;
|
|
height: 14px;
|
|
line-height: 14px;
|
|
color: #fff;
|
|
border: 1px solid map-get($rankColors, 4);
|
|
background-color: map-get($rankColors, 4);
|
|
border-left: 0;
|
|
white-space: nowrap;
|
|
border-radius: 2px;
|
|
flex-shrink: 0;
|
|
font-size: 12px;
|
|
.label {
|
|
width: 40px;
|
|
text-align: center;
|
|
padding: 0 2px;
|
|
color: #fff;
|
|
border-radius: 1px 0 0 1px;
|
|
background-color: map-get($rankColors, 4);
|
|
}
|
|
.level {
|
|
width: 16px;
|
|
background-color: #fff;
|
|
text-align: center;
|
|
color: map-get($rankColors, 4);
|
|
border-radius: 0 1px 1px 0;
|
|
}
|
|
.label,
|
|
.level {
|
|
cursor: pointer;
|
|
position: relative;
|
|
display: block;
|
|
float: left;
|
|
}
|
|
}
|
|
@for $rank from 0 to 5 {
|
|
@for $level from 1 to 5 {
|
|
$color: map-get($rankColors, $rank);
|
|
.level-#{$rank * 4 + $level} {
|
|
border-color: $color;
|
|
background-color: $color;
|
|
.label {
|
|
background-color: $color;
|
|
}
|
|
.level {
|
|
color: $color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
&.medal ul {
|
|
grid-template-columns: repeat(var(--medal-columns, 2), 1fr);
|
|
}
|
|
&.title ul {
|
|
grid-template-columns: repeat(var(--title-columns, 2), 1fr);
|
|
}
|
|
}
|
|
</style>
|