mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
add event module
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
"grapheme-splitter": "^1.0.4",
|
"grapheme-splitter": "^1.0.4",
|
||||||
"linqts": "^1.15.0",
|
"linqts": "^1.15.0",
|
||||||
"universal-cookie": "^4.0.4",
|
"universal-cookie": "^4.0.4",
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ export interface AccountInfo extends UserInfo {
|
|||||||
biliVerifyCode?: string
|
biliVerifyCode?: string
|
||||||
bindEmail?: string
|
bindEmail?: string
|
||||||
settings: UserSetting
|
settings: UserSetting
|
||||||
|
token: string
|
||||||
|
|
||||||
|
eventFetcherOnline: boolean
|
||||||
|
eventFetcherStatus: string
|
||||||
|
|
||||||
nextSendEmailTime?: number
|
nextSendEmailTime?: number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ function onLoginButtonClick() {
|
|||||||
nameOrEmail: loginModel.value.account,
|
nameOrEmail: loginModel.value.account,
|
||||||
password: loginModel.value.password,
|
password: loginModel.value.password,
|
||||||
},
|
},
|
||||||
[['Turnstile', token.value]]
|
|
||||||
)
|
)
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -183,7 +182,7 @@ function onLoginButtonClick() {
|
|||||||
</NFormItem>
|
</NFormItem>
|
||||||
</NForm>
|
</NForm>
|
||||||
<NSpace vertical justify="center" align="center">
|
<NSpace vertical justify="center" align="center">
|
||||||
<NButton :loading="!token || isLoading" type="primary" size="large" @click="onLoginButtonClick"> 登陆 </NButton>
|
<NButton :loading="isLoading" type="primary" size="large" @click="onLoginButtonClick"> 登陆 </NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
<NTabPane name="register" tab="注册">
|
<NTabPane name="register" tab="注册">
|
||||||
@@ -198,15 +197,16 @@ function onLoginButtonClick() {
|
|||||||
<NInput v-model:value="registerModel.password" type="password" @input="onPasswordInput" @keydown.enter.prevent />
|
<NInput v-model:value="registerModel.password" type="password" @input="onPasswordInput" @keydown.enter.prevent />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem ref="rPasswordFormItemRef" first path="reenteredPassword" label="重复密码">
|
<NFormItem ref="rPasswordFormItemRef" first path="reenteredPassword" label="重复密码">
|
||||||
<NInput v-model:value="registerModel.reenteredPassword" :disabled="!registerModel.password" type="password" @keydown.enter="onregisterButtonClick"/>
|
<NInput v-model:value="registerModel.reenteredPassword" :disabled="!registerModel.password" type="password" @keydown.enter="onregisterButtonClick" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
</NForm>
|
</NForm>
|
||||||
<NSpace vertical justify="center" align="center">
|
<NSpace vertical justify="center" align="center">
|
||||||
<NButton :loading="!token || isLoading" type="primary" size="large" @click="onregisterButtonClick"> 注册 </NButton>
|
<NButton :loading="!token || isLoading" type="primary" size="large" @click="onregisterButtonClick"> 注册 </NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
|
|
||||||
|
<VueTurnstile ref="turnstile" :site-key="TURNSTILE_KEY" v-model="token" theme="auto" style="text-align: center" />
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
</NTabs>
|
</NTabs>
|
||||||
<VueTurnstile ref="turnstile" :site-key="TURNSTILE_KEY" v-model="token" theme="auto" style="text-align: center" />
|
|
||||||
</template>
|
</template>
|
||||||
</NCard>
|
</NCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ const releseAPI = `https://vtsuru.suki.club/api/`
|
|||||||
|
|
||||||
export const isBackendUsable = ref(true)
|
export const isBackendUsable = ref(true)
|
||||||
|
|
||||||
|
export const AVATAR_URL = 'https://workers.vrp.moe/api/bilibili/avatar/'
|
||||||
|
|
||||||
export const BASE_API = process.env.NODE_ENV === 'development' ? debugAPI : releseAPI
|
export const BASE_API = process.env.NODE_ENV === 'development' ? debugAPI : releseAPI
|
||||||
export const FETCH_API = 'https://fetch.vtsuru.live/'
|
export const FETCH_API = 'https://fetch.vtsuru.live/'
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import RegisterAndLogin from '@/components/RegisterAndLogin.vue'
|
|
||||||
import { NCard, NDivider, NGradientText, NSpace, NText, NIcon, NGrid, NGridItem, NButton } from 'naive-ui'
|
import { NCard, NDivider, NGradientText, NSpace, NText, NIcon, NGrid, NGridItem, NButton } from 'naive-ui'
|
||||||
import vtb from '@/svgs/ic_vtuber.svg'
|
import vtb from '@/svgs/ic_vtuber.svg'
|
||||||
import { AnalyticsSharp, Calendar, Chatbox, MusicalNote } from '@vicons/ionicons5'
|
import { AnalyticsSharp, Calendar, Chatbox, MusicalNote } from '@vicons/ionicons5'
|
||||||
import { useWindowSize } from '@vueuse/core'
|
import { useWindowSize } from '@vueuse/core'
|
||||||
import { Lottery24Filled, MoreHorizontal24Filled } from '@vicons/fluent'
|
import { Lottery24Filled, MoreHorizontal24Filled, VehicleShip24Filled } from '@vicons/fluent'
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
|
|
||||||
const functions = [
|
const functions = [
|
||||||
|
{
|
||||||
|
name: '直播事件记录',
|
||||||
|
desc: '能够记录并查询上舰和SC记录 (需要另外部署脚本',
|
||||||
|
icon: VehicleShip24Filled,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '日程表',
|
name: '日程表',
|
||||||
desc: '提供多种样式的日程表 (还没做完',
|
desc: '提供多种样式的日程表 (还没做完',
|
||||||
@@ -80,12 +84,12 @@ const iconColor = 'white'
|
|||||||
</NGridItem>
|
</NGridItem>
|
||||||
</NGrid>
|
</NGrid>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NSpace style="position: absolute; bottom: 0;margin: 0 auto;width: 100vw;" justify="center">
|
<NSpace style="position: absolute; bottom: 0; margin: 0 auto; width: 100vw" justify="center">
|
||||||
<span style="color: white">
|
<span style="color: white">
|
||||||
BY
|
BY
|
||||||
<NButton tag="a" href="https://space.bilibili.com/10021741" target="_blank" text style="color: rgb(161, 236, 199)"> Megghy </NButton>
|
<NButton tag="a" href="https://space.bilibili.com/10021741" target="_blank" text style="color: rgb(161, 236, 199)"> Megghy </NButton>
|
||||||
</span>
|
</span>
|
||||||
<NDivider vertical/>
|
<NDivider vertical />
|
||||||
<span>
|
<span>
|
||||||
<NButton @click="$router.push('/about')" text> 关于 </NButton>
|
<NButton @click="$router.push('/about')" text> 关于 </NButton>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAccount } from '@/api/account'
|
import { useAccount } from '@/api/account'
|
||||||
import { NAlert, NButton, NCard, NDivider, NPopconfirm, NSpace, NTag, NText, NThing, NTime } from 'naive-ui'
|
import { NAlert, NButton, NCard, NDivider, NInput, NPopconfirm, NSpace, NTag, NText, NThing, NTime } from 'naive-ui'
|
||||||
import SettingsManageView from './SettingsManageView.vue'
|
import SettingsManageView from './SettingsManageView.vue'
|
||||||
import { useLocalStorage } from '@vueuse/core'
|
import { useLocalStorage } from '@vueuse/core'
|
||||||
|
|
||||||
@@ -28,22 +28,28 @@ function logout() {
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
|
|
||||||
<NDivider />
|
<NDivider />
|
||||||
<NAlert>
|
<NSpace vertical>
|
||||||
邮箱:
|
<NAlert>
|
||||||
<NTag v-if="accountInfo?.isEmailVerified" type="success"> 已认证 | {{ accountInfo?.bindEmail }} </NTag>
|
邮箱:
|
||||||
<template v-else>
|
<NTag v-if="accountInfo?.isEmailVerified" type="success"> 已认证 | {{ accountInfo?.bindEmail }} </NTag>
|
||||||
<NTag type="error" size="small"> 未认证 </NTag>
|
<template v-else>
|
||||||
</template>
|
<NTag type="error" size="small"> 未认证 </NTag>
|
||||||
</NAlert>
|
</template>
|
||||||
<NAlert>
|
</NAlert>
|
||||||
Bilibili 账户:
|
<NAlert>
|
||||||
<NTag v-if="accountInfo?.isBiliVerified" type="success"> 已认证 | {{ accountInfo?.biliId }} </NTag>
|
Bilibili 账户:
|
||||||
<template v-else>
|
<NTag v-if="accountInfo?.isBiliVerified" type="success"> 已认证 | {{ accountInfo?.biliId }} </NTag>
|
||||||
<NTag type="error" size="small"> 未认证 </NTag>
|
<template v-else>
|
||||||
<NDivider vertical />
|
<NTag type="error" size="small"> 未认证 </NTag>
|
||||||
<NButton size="small" @click="$router.push({ name: 'manage-biliVerify' })" type="info"> 前往认证 </NButton>
|
<NDivider vertical />
|
||||||
</template>
|
<NButton size="small" @click="$router.push({ name: 'manage-biliVerify' })" type="info"> 前往认证 </NButton>
|
||||||
</NAlert>
|
</template>
|
||||||
|
</NAlert>
|
||||||
|
<NAlert title="Token" type="info">
|
||||||
|
请注意保管, 这个东西可以完全操作你的账号
|
||||||
|
<NInput type="password" :value="accountInfo?.token" show-password-on="click" status="error"/>
|
||||||
|
</NAlert>
|
||||||
|
</NSpace>
|
||||||
<NDivider />
|
<NDivider />
|
||||||
<NSpace justify="center">
|
<NSpace justify="center">
|
||||||
<NPopconfirm @positive-click="logout">
|
<NPopconfirm @positive-click="logout">
|
||||||
@@ -58,5 +64,6 @@ function logout() {
|
|||||||
<div>
|
<div>
|
||||||
<NDivider />
|
<NDivider />
|
||||||
<SettingsManageView />
|
<SettingsManageView />
|
||||||
|
<NDivider/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,3 +1,286 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useAccount } from '@/api/account'
|
||||||
|
import { QueryGetAPI } from '@/api/query'
|
||||||
|
import { AVATAR_URL, BASE_API } from '@/data/constants'
|
||||||
|
import { Grid28Filled, List16Filled } from '@vicons/fluent'
|
||||||
|
import { format, getDaysInMonth } from 'date-fns'
|
||||||
|
import {
|
||||||
|
NAlert,
|
||||||
|
NAvatar,
|
||||||
|
NButton,
|
||||||
|
NCard,
|
||||||
|
NCollapse,
|
||||||
|
NCollapseItem,
|
||||||
|
NDatePicker,
|
||||||
|
NDivider,
|
||||||
|
NEllipsis,
|
||||||
|
NGrid,
|
||||||
|
NGridItem,
|
||||||
|
NH1,
|
||||||
|
NH2,
|
||||||
|
NH3,
|
||||||
|
NH5,
|
||||||
|
NIcon,
|
||||||
|
NLi,
|
||||||
|
NRadioButton,
|
||||||
|
NRadioGroup,
|
||||||
|
NSpace,
|
||||||
|
NSpin,
|
||||||
|
NTable,
|
||||||
|
NTag,
|
||||||
|
NText,
|
||||||
|
NTime,
|
||||||
|
NUl,
|
||||||
|
useMessage,
|
||||||
|
} from 'naive-ui'
|
||||||
|
import { computed, onMounted, ref } from 'vue'
|
||||||
|
import { saveAs } from 'file-saver'
|
||||||
|
|
||||||
|
enum EventType {
|
||||||
|
Guard,
|
||||||
|
SC,
|
||||||
|
}
|
||||||
|
interface EventModel {
|
||||||
|
type: EventType
|
||||||
|
name: string
|
||||||
|
uId: number
|
||||||
|
msg: string
|
||||||
|
time: number
|
||||||
|
num: number
|
||||||
|
price: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountInfo = useAccount()
|
||||||
|
const message = useMessage()
|
||||||
|
|
||||||
|
const rangeShortcuts = {
|
||||||
|
上个月: () => {
|
||||||
|
const cur = new Date()
|
||||||
|
const lastMonth = new Date(cur.getFullYear(), cur.getMonth() - 1)
|
||||||
|
return [new Date(cur.getFullYear(), cur.getMonth() - 1, 1).getTime(), new Date(cur.getFullYear(), cur.getMonth(), 1).getTime()] as const
|
||||||
|
},
|
||||||
|
本月: () => {
|
||||||
|
const cur = new Date()
|
||||||
|
return [new Date(cur.getFullYear(), cur.getMonth(), 1).getTime(), cur.getTime()] as const
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const selectedDate = ref<[number, number]>([rangeShortcuts.本月()[0], rangeShortcuts.本月()[1]])
|
||||||
|
const selectedType = ref(EventType.Guard)
|
||||||
|
const events = ref<EventModel[]>([])
|
||||||
|
const isLoading = ref(false)
|
||||||
|
|
||||||
|
const selectedEvents = computed(() => {
|
||||||
|
return events.value.filter((e) => e.type == selectedType.value)
|
||||||
|
})
|
||||||
|
const displayMode = ref<'grid' | 'column'>('column')
|
||||||
|
const exportType = ref<'json' | 'xml' | 'csv'>('csv')
|
||||||
|
|
||||||
|
async function onDateChange() {
|
||||||
|
isLoading.value = true
|
||||||
|
await QueryGetAPI<EventModel[]>(BASE_API + 'event/get', {
|
||||||
|
start: selectedDate.value[0],
|
||||||
|
end: selectedDate.value[1],
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
events.value = data.data
|
||||||
|
message.success('已获取数据')
|
||||||
|
//selectedType.value = type
|
||||||
|
} else {
|
||||||
|
message.error('获取数据失败: ' + data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
message.error('获取数据失败')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isLoading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function GetSCColor(price: number): string {
|
||||||
|
if (price === 0) return `#2a60b2`
|
||||||
|
if (price > 0 && price < 30) return `#2a60b2`
|
||||||
|
if (price >= 30 && price < 50) return `#2a60b2`
|
||||||
|
if (price >= 50 && price < 100) return `#427d9e`
|
||||||
|
if (price >= 100 && price < 500) return `#c99801`
|
||||||
|
if (price >= 500 && price < 1000) return `#e09443`
|
||||||
|
if (price >= 1000 && price < 2000) return `#e54d4d`
|
||||||
|
if (price >= 2000) return `#ab1a32`
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
function GetGuardColor(price: number | null | undefined): string {
|
||||||
|
if (price) {
|
||||||
|
if (price < 138) return ''
|
||||||
|
if (price >= 138 && price < 1598) return 'rgb(104, 136, 241)'
|
||||||
|
if (price >= 1598 && price < 15998) return 'rgb(157, 155, 255)'
|
||||||
|
if (price >= 15998) return 'rgb(122, 4, 35)'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
function exportData() {
|
||||||
|
let text = ''
|
||||||
|
switch (exportType.value) {
|
||||||
|
case 'json': {
|
||||||
|
text = JSON.stringify(selectedEvents.value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'csv': {
|
||||||
|
text = objectsToCSV(
|
||||||
|
selectedEvents.value.map((v) => ({
|
||||||
|
type: v.type,
|
||||||
|
time: format(v.time, 'yyyy-MM-dd HH:mm:ss'),
|
||||||
|
name: v.name,
|
||||||
|
uId: v.uId,
|
||||||
|
num: v.num,
|
||||||
|
price: v.price,
|
||||||
|
msg: v.msg,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveAs(
|
||||||
|
new Blob([text], { type: 'text/plain;charset=utf-8' }),
|
||||||
|
`${format(Date.now(), 'yyyy-MM-dd HH:mm:ss')}_${format(selectedDate.value[0], 'yyyy-MM-dd HH:mm:ss')}_${format(selectedDate.value[1], 'yyyy-MM-dd HH:mm:ss')}}_${accountInfo.value?.id}_${
|
||||||
|
accountInfo.value?.name
|
||||||
|
}_${selectedType.value}.${exportType.value}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function objectsToCSV(arr: any[]) {
|
||||||
|
const array = [Object.keys(arr[0])].concat(arr)
|
||||||
|
return array
|
||||||
|
.map((row) => {
|
||||||
|
return Object.values(row)
|
||||||
|
.map((value) => {
|
||||||
|
return typeof value === 'string' ? JSON.stringify(value) : value
|
||||||
|
})
|
||||||
|
.toString()
|
||||||
|
})
|
||||||
|
.join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (accountInfo.value?.eventFetcherOnline) onDateChange()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
编写中...
|
<NAlert type="warning"> 实验性功能, 尚不稳定. </NAlert>
|
||||||
</template>
|
<NDivider />
|
||||||
|
<NAlert title="EVENT-FETCHER 状态" :type="accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? 'success' : 'warning') : 'info'">
|
||||||
|
<NTag :type="accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? 'success' : 'warning') : 'error'">
|
||||||
|
{{ accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? '正常' : `异常: ${accountInfo.eventFetcherStatus}`) : '未连接' }}
|
||||||
|
</NTag>
|
||||||
|
</NAlert>
|
||||||
|
<NDivider />
|
||||||
|
<NCard size="small" style="witdh: 100%">
|
||||||
|
<template v-if="accountInfo?.eventFetcherOnline">
|
||||||
|
<NSpace justify="center" align="center">
|
||||||
|
<NDatePicker v-model:value="selectedDate" @update:value="onDateChange" type="datetimerange" :shortcuts="rangeShortcuts" start-placeholder="开始时间" end-placeholder="结束时间" />
|
||||||
|
<NRadioGroup v-model:value="selectedType">
|
||||||
|
<NRadioButton :value="EventType.Guard">舰长</NRadioButton>
|
||||||
|
<NRadioButton :value="EventType.SC">Superchat</NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
<NButton @click="onDateChange" type="primary" :loading="isLoading"> 刷新 </NButton>
|
||||||
|
</NSpace>
|
||||||
|
<br />
|
||||||
|
<NCard title="导出" size="small">
|
||||||
|
<NSpace>
|
||||||
|
<NRadioGroup v-model:value="exportType" style="margin: 0 auto">
|
||||||
|
<NRadioButton value="csv"> CSV </NRadioButton>
|
||||||
|
<NRadioButton value="json"> Json </NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
<NButton @click="exportData" type="primary"> 导出 </NButton>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
<NDivider> 共 {{ selectedEvents.length }} 条 </NDivider>
|
||||||
|
<NSpin :show="isLoading">
|
||||||
|
<NRadioGroup v-model:value="displayMode" style="display: flex; justify-content: center" size="small">
|
||||||
|
<NRadioButton value="column">
|
||||||
|
<NIcon :component="List16Filled" />
|
||||||
|
</NRadioButton>
|
||||||
|
<NRadioButton value="grid">
|
||||||
|
<NIcon :component="Grid28Filled" />
|
||||||
|
</NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
<br />
|
||||||
|
<Transition mode="out-in" name="fade" appear>
|
||||||
|
<div v-if="displayMode == 'grid'">
|
||||||
|
<NGrid cols="1 500:2 800:3 1000:4" :x-gap="12" :y-gap="8">
|
||||||
|
<NGridItem v-for="item in selectedEvents" v-bind:key="item.time">
|
||||||
|
<NCard size="small" :style="`height: ${selectedType == EventType.Guard ? '175px' : '220'}px`">
|
||||||
|
<NSpace align="center" vertical :size="5">
|
||||||
|
<NAvatar round lazy borderd :size="64" :src="AVATAR_URL + item.uId" :img-props="{ referrerpolicy: 'no-referrer' }" style="box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2)" />
|
||||||
|
<NSpace>
|
||||||
|
<NTag size="tiny" v-if="selectedType == EventType.Guard" :bordered="false"> {{ item.msg }} </NTag>
|
||||||
|
<NTag v-if="selectedType == EventType.Guard" size="tiny" round :color="{ color: GetGuardColor(item.price), textColor: 'white', borderColor: 'white' }"> {{ item.price }} </NTag>
|
||||||
|
<NTag v-else-if="selectedType == EventType.SC" size="tiny" round :color="{ color: GetSCColor(item.price), textColor: 'white', borderColor: 'white' }"> {{ item.price }} </NTag>
|
||||||
|
</NSpace>
|
||||||
|
<NText>
|
||||||
|
{{ item.name }}
|
||||||
|
</NText>
|
||||||
|
<NText depth="3" style="font-size: small"> <NTime :time="item.time" /> </NText>
|
||||||
|
<NEllipsis v-if="selectedType == EventType.SC">
|
||||||
|
{{ item.msg }}
|
||||||
|
</NEllipsis>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
</NGridItem>
|
||||||
|
</NGrid>
|
||||||
|
</div>
|
||||||
|
<NTable v-else>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>用户名</th>
|
||||||
|
<th>UId</th>
|
||||||
|
<th>时间</th>
|
||||||
|
<th v-if="selectedType == EventType.Guard">类型</th>
|
||||||
|
<th>价格</th>
|
||||||
|
<th v-if="selectedType == EventType.SC">内容</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-for="item in selectedEvents" v-bind:key="item.time">
|
||||||
|
<tr>
|
||||||
|
<td>{{ item.name }}</td>
|
||||||
|
<td>{{ item.uId }}</td>
|
||||||
|
<td><NTime :time="item.time" /></td>
|
||||||
|
<td v-if="selectedType == EventType.Guard">{{ item.msg }}</td>
|
||||||
|
<td>
|
||||||
|
<NTag :color="{ color: selectedType == EventType.Guard ? GetGuardColor(item.price) : GetSCColor(item.price), textColor: 'white', borderColor: 'white' }"> {{ item.price }} </NTag>
|
||||||
|
</td>
|
||||||
|
<td v-if="selectedType == EventType.SC">
|
||||||
|
<NEllipsis style="max-width: 300px">{{ item.msg }}</NEllipsis>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</NTable>
|
||||||
|
</Transition>
|
||||||
|
</NSpin>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<NCollapse :default-expanded-names="['1']">
|
||||||
|
<NCollapseItem title="这是什么?" name="1"> 可以查看曾经收到的Superchat以及上舰记录, 并导出为 CSV 之类的表格 </NCollapseItem>
|
||||||
|
<NCollapseItem title="可以直接用吗"> 遗憾的是并不能, 使用这个功能需要你拥有一个可以7*24小时运行 Docker 容器或者 Node.js 脚本的环境, 并且可以访问互联网 </NCollapseItem>
|
||||||
|
<NCollapseItem title="有没有什么要求?">
|
||||||
|
关于环境的话理论上能够运行 Docker 或者 Node.js 的环境都能可以
|
||||||
|
<br /><br />
|
||||||
|
此外, 你至少需要以下技能之一:
|
||||||
|
<NUl>
|
||||||
|
<NLi>了解并能够使用 Docker 容器</NLi>
|
||||||
|
<NLi>了解并能够运行 Node.js</NLi>
|
||||||
|
<NLi>熟悉互联网冲浪, 能够跟着教程点击鼠标</NLi>
|
||||||
|
<NLi>拥有掌握以上技能的 stf 或者朋友</NLi>
|
||||||
|
</NUl>
|
||||||
|
<NH3>
|
||||||
|
<NText strong> 即使你对相关知识一窍不通也不用担心, 跟着后面的傻瓜教程中的 Koyeb 也可以完成部署. 理论上这玩意里头的免费套餐就够用了, 当然如果你想要更稳一点上个付费套餐也不影响 </NText>
|
||||||
|
</NH3>
|
||||||
|
</NCollapseItem>
|
||||||
|
</NCollapse>
|
||||||
|
<NDivider style="margin-bottom: 10px" />
|
||||||
|
<NSpace justify="center">
|
||||||
|
<NButton tag="a" href="https://www.yuque.com/megghy/dez70g/vfvcyv3024xvaa1p" target="_blank" type="primary"> 部署指南 </NButton>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
</NCard>
|
||||||
|
</template>
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ const fakeSchedule = [
|
|||||||
},
|
},
|
||||||
] as ScheduleWeekInfo[]
|
] as ScheduleWeekInfo[]
|
||||||
const selectedOption = ref(templateOptions[0].value)
|
const selectedOption = ref(templateOptions[0].value)
|
||||||
|
const selectedTab = ref('general')
|
||||||
|
|
||||||
const scheduleTemplateOptions = [
|
const scheduleTemplateOptions = [
|
||||||
{
|
{
|
||||||
@@ -236,7 +237,7 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NCard v-if="accountInfo" title="设置" style="min-height: 800px">
|
<NCard v-if="accountInfo" title="设置" :style="`${selectedTab === 'general' ? '' : 'min-height: 800px;'}`">
|
||||||
<NTabs>
|
<NTabs>
|
||||||
<NTabPane tab="常规" name="general">
|
<NTabPane tab="常规" name="general">
|
||||||
<NDivider style="margin: 0"> 启用功能 </NDivider>
|
<NDivider style="margin: 0"> 启用功能 </NDivider>
|
||||||
|
|||||||
@@ -1529,6 +1529,11 @@ file-entry-cache@^6.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flat-cache "^3.0.4"
|
flat-cache "^3.0.4"
|
||||||
|
|
||||||
|
file-saver@^2.0.5:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
|
||||||
|
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
|
||||||
|
|
||||||
fill-range@^7.0.1:
|
fill-range@^7.0.1:
|
||||||
version "7.0.1"
|
version "7.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||||
|
|||||||
Reference in New Issue
Block a user