mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
fix danmakutype: enter
This commit is contained in:
@@ -25,7 +25,6 @@ import {
|
|||||||
NList,
|
NList,
|
||||||
NListItem,
|
NListItem,
|
||||||
NModal,
|
NModal,
|
||||||
NPopover,
|
|
||||||
NRadioButton,
|
NRadioButton,
|
||||||
NRadioGroup,
|
NRadioGroup,
|
||||||
NSkeleton,
|
NSkeleton,
|
||||||
@@ -34,7 +33,6 @@ import {
|
|||||||
NSwitch,
|
NSwitch,
|
||||||
NTag,
|
NTag,
|
||||||
NTooltip,
|
NTooltip,
|
||||||
NVirtualList,
|
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||||
import LiveInfoContainer from './LiveInfoContainer.vue'
|
import LiveInfoContainer from './LiveInfoContainer.vue'
|
||||||
@@ -57,11 +55,11 @@ const accountInfo = useAccount()
|
|||||||
const debouncedFn = useDebounceFn(() => {
|
const debouncedFn = useDebounceFn(() => {
|
||||||
UpdateDanmakus()
|
UpdateDanmakus()
|
||||||
}, 750)
|
}, 750)
|
||||||
let isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
let showModal = ref(false)
|
const showModal = ref(false)
|
||||||
let showExportModal = ref(false)
|
const showExportModal = ref(false)
|
||||||
let userDanmakus = ref<DanmakuModel[] | undefined>()
|
const userDanmakus = ref<DanmakuModel[] | undefined>()
|
||||||
let hideAvatar = useLocalStorage('Setting.HideAvatar', false)
|
const hideAvatar = useLocalStorage('Setting.HideAvatar', false)
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -113,7 +111,7 @@ const emit = defineEmits<{
|
|||||||
defineExpose({
|
defineExpose({
|
||||||
InsertDanmakus,
|
InsertDanmakus,
|
||||||
})
|
})
|
||||||
let danmakus = ref<DanmakuModel[]>([])
|
const danmakus = ref<DanmakuModel[]>([])
|
||||||
watch(
|
watch(
|
||||||
() => showTools,
|
() => showTools,
|
||||||
(newV, oldV) => {
|
(newV, oldV) => {
|
||||||
@@ -128,25 +126,26 @@ watch(danmakuRef, (newValue) => {
|
|||||||
danmakus.value = GetFilteredDanmakus(newValue)
|
danmakus.value = GetFilteredDanmakus(newValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
let keyword = ref('')
|
const keyword = ref('')
|
||||||
let enableRegex = ref(false)
|
const enableRegex = ref(false)
|
||||||
let deselect = ref(false)
|
const deselect = ref(false)
|
||||||
let price = ref<number | undefined>()
|
const price = ref<number | undefined>()
|
||||||
let filterSelected = ref(defaultFilterSelected)
|
const filterSelected = ref(defaultFilterSelected)
|
||||||
let innerShowTools = ref(showTools)
|
const innerShowTools = ref(showTools)
|
||||||
let modalShowTools = ref(false)
|
const modalShowTools = ref(false)
|
||||||
let orderDecreasing = ref(false)
|
const orderDecreasing = ref(false)
|
||||||
let orderByPrice = ref(false)
|
const orderByPrice = ref(false)
|
||||||
let processing = ref(false)
|
const processing = ref(false)
|
||||||
let isRanking = ref(false)
|
const isRanking = ref(false)
|
||||||
let rankInfo = ref<RankInfo[]>([])
|
const rankInfo = ref<RankInfo[]>([])
|
||||||
let currentRankInfo = ref<RankInfo[]>([])
|
const currentRankInfo = ref<RankInfo[]>([])
|
||||||
let rankType = ref(RankType.Danmaku)
|
const rankType = ref(RankType.Danmaku)
|
||||||
let hideEmoji = ref(false)
|
const hideEmoji = ref(false)
|
||||||
|
const existEnterMessage = ref(false)
|
||||||
|
|
||||||
let exportType = ref<'json' | 'xml' | 'csv'>('json')
|
const exportType = ref<'json' | 'xml' | 'csv'>('json')
|
||||||
let onlyExportFilteredDanmakus = ref(false)
|
const onlyExportFilteredDanmakus = ref(false)
|
||||||
let isExporting = ref(false)
|
const isExporting = ref(false)
|
||||||
|
|
||||||
function OnNameClick(uId: number) {
|
function OnNameClick(uId: number) {
|
||||||
if (isInModal) {
|
if (isInModal) {
|
||||||
@@ -257,7 +256,17 @@ function GetRankIndexColor(index: number) {
|
|||||||
function Export() {
|
function Export() {
|
||||||
isExporting.value = true
|
isExporting.value = true
|
||||||
saveAs(
|
saveAs(
|
||||||
new Blob([GetString(accountInfo.value, currentLive, onlyExportFilteredDanmakus.value ? danmakus.value : currentDanmakus, exportType.value)], { type: 'text/plain;charset=utf-8' }),
|
new Blob(
|
||||||
|
[
|
||||||
|
GetString(
|
||||||
|
accountInfo.value,
|
||||||
|
currentLive,
|
||||||
|
onlyExportFilteredDanmakus.value ? danmakus.value : currentDanmakus,
|
||||||
|
exportType.value,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
{ type: 'text/plain;charset=utf-8' },
|
||||||
|
),
|
||||||
`${Date.now()}_${currentLive.startAt}_${currentLive.title.replace('_', '-')}_${accountInfo.value?.name}.${exportType.value}`,
|
`${Date.now()}_${currentLive.startAt}_${currentLive.title.replace('_', '-')}_${accountInfo.value?.name}.${exportType.value}`,
|
||||||
)
|
)
|
||||||
isExporting.value = false
|
isExporting.value = false
|
||||||
@@ -283,7 +292,9 @@ function GetFilteredDanmakus(targetDanmakus?: DanmakuModel[]) {
|
|||||||
tempDanmakus = tempDanmakus.filter((d) => d.type != EventDataTypes.Message || !d.isEmoji)
|
tempDanmakus = tempDanmakus.filter((d) => d.type != EventDataTypes.Message || !d.isEmoji)
|
||||||
}
|
}
|
||||||
if (orderByPrice.value) {
|
if (orderByPrice.value) {
|
||||||
tempDanmakus = tempDanmakus.filter((d) => d.type != EventDataTypes.Message).sort((a, b) => (a.price ?? 0) - (b.price ?? 0))
|
tempDanmakus = tempDanmakus
|
||||||
|
.filter((d) => d.type != EventDataTypes.Message)
|
||||||
|
.sort((a, b) => (a.price ?? 0) - (b.price ?? 0))
|
||||||
} else {
|
} else {
|
||||||
tempDanmakus = tempDanmakus.sort((a, b) => a.time - b.time)
|
tempDanmakus = tempDanmakus.sort((a, b) => a.time - b.time)
|
||||||
}
|
}
|
||||||
@@ -295,7 +306,11 @@ function GetFilteredDanmakus(targetDanmakus?: DanmakuModel[]) {
|
|||||||
if (d.uId.toString() == keyword.value || d.uName == keyword.value) {
|
if (d.uId.toString() == keyword.value || d.uName == keyword.value) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return enableRegex.value ? (d.msg?.match(keyword.value) ? true : false) : d.msg?.toLowerCase().includes(keyword.value.toLowerCase()) == true
|
return enableRegex.value
|
||||||
|
? d.msg?.match(keyword.value)
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
: d.msg?.toLowerCase().includes(keyword.value.toLowerCase()) == true
|
||||||
}
|
}
|
||||||
if (price.value && price.value > 0) {
|
if (price.value && price.value > 0) {
|
||||||
tempDanmakus = tempDanmakus.filter((d) => (d.price ?? 0) >= (price.value ?? 0))
|
tempDanmakus = tempDanmakus.filter((d) => (d.price ?? 0) >= (price.value ?? 0))
|
||||||
@@ -317,14 +332,22 @@ function RoundNumber(num: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
danmakus.value = currentDanmakus
|
danmakus.value = GetFilteredDanmakus()
|
||||||
|
existEnterMessage.value = danmakus.value.some((d) => d.type == EventDataTypes.Message)
|
||||||
|
//defaultFilterSelected.push(EventDataTypes.Enter)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NSkeleton v-if="isLoading"> </NSkeleton>
|
<NSkeleton v-if="isLoading"> </NSkeleton>
|
||||||
<NSpin v-else :show="processing">
|
<NSpin v-else :show="processing">
|
||||||
<NModal v-model:show="showModal" @after-leave="userDanmakus = undefined" preset="card" :style="'width: 600px;max-width: 90vw;max-height: 90vh;'" content-style="overflow-y: auto">
|
<NModal
|
||||||
|
v-model:show="showModal"
|
||||||
|
@after-leave="userDanmakus = undefined"
|
||||||
|
preset="card"
|
||||||
|
:style="'width: 600px;max-width: 90vw;max-height: 90vh;'"
|
||||||
|
content-style="overflow-y: auto"
|
||||||
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
{{ userDanmakus?.[0].uName }}
|
{{ userDanmakus?.[0].uName }}
|
||||||
</template>
|
</template>
|
||||||
@@ -337,7 +360,15 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
</NSwitch>
|
</NSwitch>
|
||||||
</template>
|
</template>
|
||||||
<DanmakuContainer :show-live-info="false" :current-danmakus="userDanmakus ?? []" :current-live="currentLive" :height="500" :show-border="false" :show-tools="modalShowTools" to="space" />
|
<DanmakuContainer
|
||||||
|
:show-live-info="false"
|
||||||
|
:current-danmakus="userDanmakus ?? []"
|
||||||
|
:current-live="currentLive"
|
||||||
|
:height="500"
|
||||||
|
:show-border="false"
|
||||||
|
:show-tools="modalShowTools"
|
||||||
|
to="space"
|
||||||
|
/>
|
||||||
</NModal>
|
</NModal>
|
||||||
<NModal v-model:show="showExportModal" preset="card" style="width: 500px; max-width: 90vw; height: auto">
|
<NModal v-model:show="showExportModal" preset="card" style="width: 500px; max-width: 90vw; height: auto">
|
||||||
<template #header> 导出 </template>
|
<template #header> 导出 </template>
|
||||||
@@ -363,9 +394,10 @@ onMounted(() => {
|
|||||||
<NCollapse>
|
<NCollapse>
|
||||||
<NCollapseItem title="关于" name="1">
|
<NCollapseItem title="关于" name="1">
|
||||||
<div>
|
<div>
|
||||||
文件名格式: {<NTooltip><template #trigger>生成时间</template>Unix</NTooltip>}_{<NTooltip><template #trigger>开始时间</template>Unix: {{ currentLive.startAt }} </NTooltip>}_{<NTooltip
|
文件名格式: {<NTooltip><template #trigger>生成时间</template>Unix</NTooltip>}_{<NTooltip
|
||||||
><template #trigger>直播间标题</template>' _ ' 将被转义为 ' - '</NTooltip
|
><template #trigger>开始时间</template>Unix: {{ currentLive.startAt }} </NTooltip
|
||||||
>}_{<NTooltip><template #trigger>用户名</template>{{ accountInfo?.name }}</NTooltip
|
>}_{<NTooltip><template #trigger>直播间标题</template>' _ ' 将被转义为 ' - '</NTooltip>}_{<NTooltip
|
||||||
|
><template #trigger>用户名</template>{{ accountInfo?.name }}</NTooltip
|
||||||
>}.{{ exportType }}
|
>}.{{ exportType }}
|
||||||
<br />
|
<br />
|
||||||
弹幕Type对应:
|
弹幕Type对应:
|
||||||
@@ -410,7 +442,9 @@ onMounted(() => {
|
|||||||
<NCollapseTransition :show="innerShowTools && !isRanking">
|
<NCollapseTransition :show="innerShowTools && !isRanking">
|
||||||
<NSpace vertical style="padding-bottom: 16px">
|
<NSpace vertical style="padding-bottom: 16px">
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
<NButton type="primary" size="small" @click="showExportModal = true" @update:value="UpdateDanmakus"> 导出 </NButton>
|
<NButton type="primary" size="small" @click="showExportModal = true" @update:value="UpdateDanmakus">
|
||||||
|
导出
|
||||||
|
</NButton>
|
||||||
<NCheckbox v-model:checked="orderDecreasing" @update:checked="UpdateDanmakus"> 降序 </NCheckbox>
|
<NCheckbox v-model:checked="orderDecreasing" @update:checked="UpdateDanmakus"> 降序 </NCheckbox>
|
||||||
<NCollapseTransition :show="filterSelected.includes(EventDataTypes.Message)">
|
<NCollapseTransition :show="filterSelected.includes(EventDataTypes.Message)">
|
||||||
<NCheckbox v-model:checked="hideEmoji" @update:checked="UpdateDanmakus"> 隐藏表情 </NCheckbox>
|
<NCheckbox v-model:checked="hideEmoji" @update:checked="UpdateDanmakus"> 隐藏表情 </NCheckbox>
|
||||||
@@ -419,7 +453,14 @@ onMounted(() => {
|
|||||||
<NCheckbox v-model:checked="orderByPrice" @update:checked="UpdateDanmakus"> 按价格排序 </NCheckbox>
|
<NCheckbox v-model:checked="orderByPrice" @update:checked="UpdateDanmakus"> 按价格排序 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
<NInput v-model:value="keyword" size="small" style="max-width: 200px" placeholder="内容筛选" clearable @update:value="debouncedFn">
|
<NInput
|
||||||
|
v-model:value="keyword"
|
||||||
|
size="small"
|
||||||
|
style="max-width: 200px"
|
||||||
|
placeholder="内容筛选"
|
||||||
|
clearable
|
||||||
|
@update:value="debouncedFn"
|
||||||
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<NIcon :component="Search24Filled" />
|
<NIcon :component="Search24Filled" />
|
||||||
</template>
|
</template>
|
||||||
@@ -428,7 +469,15 @@ onMounted(() => {
|
|||||||
<NCheckbox v-model:checked="deselect" @update:checked="UpdateDanmakus"> 反选 </NCheckbox>
|
<NCheckbox v-model:checked="deselect" @update:checked="UpdateDanmakus"> 反选 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
<NInputNumber v-model:value="price" placeholder="最低价格" size="small" style="max-width: 200px" clearable :min="0" @update:value="debouncedFn">
|
<NInputNumber
|
||||||
|
v-model:value="price"
|
||||||
|
placeholder="最低价格"
|
||||||
|
size="small"
|
||||||
|
style="max-width: 200px"
|
||||||
|
clearable
|
||||||
|
:min="0"
|
||||||
|
@update:value="debouncedFn"
|
||||||
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<NIcon :component="Money20Regular" />
|
<NIcon :component="Money20Regular" />
|
||||||
</template>
|
</template>
|
||||||
@@ -445,6 +494,8 @@ onMounted(() => {
|
|||||||
<NCheckbox :value="EventDataTypes.Gift" label="礼物" />
|
<NCheckbox :value="EventDataTypes.Gift" label="礼物" />
|
||||||
<NCheckbox :value="EventDataTypes.Guard" label="舰长" />
|
<NCheckbox :value="EventDataTypes.Guard" label="舰长" />
|
||||||
<NCheckbox :value="EventDataTypes.SC" label="Superchat" />
|
<NCheckbox :value="EventDataTypes.SC" label="Superchat" />
|
||||||
|
|
||||||
|
<NCheckbox v-if="existEnterMessage" :value="EventDataTypes.Enter" label="入场" />
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NCheckboxGroup>
|
</NCheckboxGroup>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
@@ -462,15 +513,39 @@ onMounted(() => {
|
|||||||
</NDivider>
|
</NDivider>
|
||||||
</NCollapseTransition>
|
</NCollapseTransition>
|
||||||
<div :style="isRanking ? 'display:none' : ''">
|
<div :style="isRanking ? 'display:none' : ''">
|
||||||
<SimpleVirtualList v-if="danmakus.length > itemRange" :items="danmakus" :default-size="itemHeight" :default-height="height ?? 1000">
|
<SimpleVirtualList
|
||||||
|
v-if="danmakus.length > itemRange"
|
||||||
|
:items="danmakus"
|
||||||
|
:default-size="itemHeight"
|
||||||
|
:default-height="height ?? 1000"
|
||||||
|
>
|
||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<p :style="`min-height: ${itemHeight}px;width:97%;display:flex;align-items:center;`">
|
<p :style="`min-height: ${itemHeight}px;width:97%;display:flex;align-items:center;`">
|
||||||
<DanmakuItem :danmaku="item" :account-info="accountInfo" @on-click-name="OnNameClick" :show-name="showName" :show-avatar="!hideAvatar" :height="itemHeight" />
|
<DanmakuItem
|
||||||
|
:danmaku="item"
|
||||||
|
:account-info="accountInfo"
|
||||||
|
@on-click-name="OnNameClick"
|
||||||
|
:show-name="showName"
|
||||||
|
:show-avatar="!hideAvatar"
|
||||||
|
:height="itemHeight"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</SimpleVirtualList>
|
</SimpleVirtualList>
|
||||||
<p v-else v-for="item in danmakus" :style="`min-height: ${itemHeight}px;width:97%;display:flex;align-items:center;`" v-bind:key="item.id">
|
<p
|
||||||
<DanmakuItem :danmaku="item" :account-info="accountInfo" @on-click-name="OnNameClick" :show-name="showName" :show-avatar="!hideAvatar" :height="itemHeight" />
|
v-else
|
||||||
|
v-for="item in danmakus"
|
||||||
|
:style="`min-height: ${itemHeight}px;width:97%;display:flex;align-items:center;`"
|
||||||
|
v-bind:key="item.id"
|
||||||
|
>
|
||||||
|
<DanmakuItem
|
||||||
|
:danmaku="item"
|
||||||
|
:account-info="accountInfo"
|
||||||
|
@on-click-name="OnNameClick"
|
||||||
|
:show-name="showName"
|
||||||
|
:show-avatar="!hideAvatar"
|
||||||
|
:height="itemHeight"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isRanking">
|
<div v-if="isRanking">
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const renderCountdown: CountdownProps['render'] = (info: { hours: number; minute
|
|||||||
}
|
}
|
||||||
function onClick() {
|
function onClick() {
|
||||||
if (props.canClick == true) {
|
if (props.canClick == true) {
|
||||||
console.log(props.item.id)
|
|
||||||
router.push({ name: 'manage-videoCollect-Detail', params: { id: props.item.id } })
|
router.push({ name: 'manage-videoCollect-Detail', params: { id: props.item.id } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,13 +101,13 @@ const createRules: FormRules = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const paddingVideos = computed(() => {
|
const paddingVideos = computed(() => {
|
||||||
return videoDetail.value.videos.filter((v) => v.info.status == VideoStatus.Pending)
|
return videoDetail.value?.videos?.filter((v) => v.info.status == VideoStatus.Pending) ?? []
|
||||||
})
|
})
|
||||||
const rejectVideos = computed(() => {
|
const rejectVideos = computed(() => {
|
||||||
return videoDetail.value.videos.filter((v) => v.info.status == VideoStatus.Rejected)
|
return videoDetail.value?.videos?.filter((v) => v.info.status == VideoStatus.Rejected) ?? []
|
||||||
})
|
})
|
||||||
const acceptVideos = computed(() => {
|
const acceptVideos = computed(() => {
|
||||||
return videoDetail.value.videos.filter((v) => v.info.status == VideoStatus.Accepted)
|
return videoDetail.value?.videos?.filter((v) => v.info.status == VideoStatus.Accepted) ?? []
|
||||||
})
|
})
|
||||||
|
|
||||||
async function getData() {
|
async function getData() {
|
||||||
@@ -121,6 +121,7 @@ async function getData() {
|
|||||||
description: data.data.table.description,
|
description: data.data.table.description,
|
||||||
maxVideoCount: data.data.table.maxVideoCount,
|
maxVideoCount: data.data.table.maxVideoCount,
|
||||||
} as VideoCollectCreateModel
|
} as VideoCollectCreateModel
|
||||||
|
console.log(data.data)
|
||||||
return data.data
|
return data.data
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user