mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
Compare commits
3 Commits
ec619b404d
...
a5420e5914
| Author | SHA1 | Date | |
|---|---|---|---|
| a5420e5914 | |||
| 4ebfeaec69 | |||
| 8f734af8b3 |
@@ -239,7 +239,6 @@ export interface Setting_Point {
|
||||
maxBonusPoints: number // 最大奖励积分
|
||||
allowSelfCheckIn: boolean // 是否允许自己签到
|
||||
requireAuth: boolean // 是否需要认证
|
||||
allowCheckInRanking: boolean // 是否允许查询签到排行
|
||||
}
|
||||
export interface Setting_QuestionDisplay {
|
||||
font?: string // Optional string, with a maximum length of 30 characters
|
||||
@@ -293,10 +292,11 @@ export enum FunctionTypes {
|
||||
SongList,
|
||||
QuestionBox,
|
||||
Schedule,
|
||||
SongRequest,
|
||||
LiveRequest,
|
||||
Queue,
|
||||
Point,
|
||||
VideoCollect
|
||||
VideoCollect,
|
||||
CheckInRanking,
|
||||
}
|
||||
export interface SongAuthorInfo {
|
||||
name: string
|
||||
@@ -777,7 +777,7 @@ export interface ResponsePointOrder2OwnerModel {
|
||||
createAt: number
|
||||
updateAt: number
|
||||
status: PointOrderStatus
|
||||
|
||||
remark?: string
|
||||
trackingNumber?: string
|
||||
expressCompany?: string
|
||||
}
|
||||
@@ -791,6 +791,7 @@ export interface ResponsePointOrder2UserModel {
|
||||
goods: ResponsePointGoodModel
|
||||
status: PointOrderStatus
|
||||
createAt: number
|
||||
remark?: string
|
||||
|
||||
trackingNumber?: string
|
||||
expressCompany?: string
|
||||
|
||||
@@ -148,8 +148,8 @@
|
||||
|
||||
<NFormItem label="允许查看签到排行">
|
||||
<NSwitch
|
||||
v-model:value="serverSetting.allowCheckInRanking"
|
||||
@update:value="updateServerSettings"
|
||||
:value="accountInfo.settings.enableFunctions.includes(FunctionTypes.CheckInRanking)"
|
||||
@update:value="updateCheckInRanking"
|
||||
/>
|
||||
<template #feedback>
|
||||
启用后,用户可以查看签到排行榜
|
||||
@@ -381,8 +381,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SaveSetting, useAccount } from '@/api/account';
|
||||
import { CheckInRankingInfo, CheckInResult } from '@/api/api-models';
|
||||
import { SaveEnableFunctions, SaveSetting, useAccount } from '@/api/account';
|
||||
import { CheckInRankingInfo, CheckInResult, FunctionTypes } from '@/api/api-models';
|
||||
import { QueryGetAPI } from '@/api/query';
|
||||
import { useAutoAction } from '@/client/store/useAutoAction';
|
||||
import { CHECKIN_API_URL } from '@/data/constants';
|
||||
@@ -791,6 +791,10 @@ async function handleTestCheckIn() {
|
||||
});
|
||||
}
|
||||
}
|
||||
function updateCheckInRanking(value: boolean) {
|
||||
accountInfo.value.settings.enableFunctions = value ? [...accountInfo.value.settings.enableFunctions, FunctionTypes.CheckInRanking] : accountInfo.value.settings.enableFunctions.filter(f => f !== FunctionTypes.CheckInRanking);
|
||||
SaveEnableFunctions(accountInfo.value.settings.enableFunctions);
|
||||
}
|
||||
|
||||
// 组件挂载时加载排行榜
|
||||
onMounted(() => {
|
||||
|
||||
@@ -156,7 +156,6 @@ function getScoreColor(score: number | undefined): string {
|
||||
lazy
|
||||
/>
|
||||
</NSpace>
|
||||
<NDivider style="margin: 10px 0;" />
|
||||
</template>
|
||||
|
||||
<NText
|
||||
|
||||
@@ -119,20 +119,32 @@ defineExpose({
|
||||
|
||||
// --- 计算属性 ---
|
||||
|
||||
// 新增:计算是否需要显示试听开关
|
||||
const canShowListenSwitch = computed(() => {
|
||||
const audioRegex = /\.(mp3|flac|ogg|wav|m4a)$/i;
|
||||
return songsInternal.value.some(song => song.url && audioRegex.test(song.url));
|
||||
});
|
||||
|
||||
// 新增:计算是否需要显示链接开关
|
||||
const canShowLinkSwitch = computed(() => {
|
||||
const linkSources = [SongFrom.Netease, SongFrom.FiveSing, SongFrom.Kugou]; // Corrected sources
|
||||
return songsInternal.value.some(song => song.url || (song.from != null && linkSources.includes(song.from))); // Check url OR valid from source
|
||||
});
|
||||
|
||||
// 计算操作列的预定义宽度
|
||||
const actionColumnWidth = computed(() => {
|
||||
const baseSelfWidth = 85; // 基础宽度 (isSelf=true, 编辑+删除)
|
||||
const baseSelfWidth = 80; // 基础宽度 (isSelf=true, 编辑+删除)
|
||||
const basePublicWidth = 40; // 基础宽度 (isSelf=false)
|
||||
const listenButtonWidth = 40;
|
||||
const linkButtonWidth = 40;
|
||||
const linkButtonWidth = 50;
|
||||
const extraButtonWidth = 40; // 假设的额外按钮宽度
|
||||
|
||||
let width = props.isSelf ? baseSelfWidth : basePublicWidth;
|
||||
|
||||
if (showListenButton.value) {
|
||||
if (showListenButton.value && canShowListenSwitch.value) {
|
||||
width += listenButtonWidth;
|
||||
}
|
||||
if (showLinkButton.value) {
|
||||
if (showLinkButton.value && canShowLinkSwitch.value) {
|
||||
width += linkButtonWidth;
|
||||
}
|
||||
if (props.extraButton) {
|
||||
@@ -351,7 +363,7 @@ function createColumns(): DataTableColumns<SongsInfo> {
|
||||
{
|
||||
title: '标签',
|
||||
key: 'tags',
|
||||
width: 150, // 调整宽度
|
||||
minWidth: 100,
|
||||
resizable: true,
|
||||
// 列筛选选项
|
||||
filterOptions: tagsSelectOption.value,
|
||||
@@ -452,17 +464,7 @@ function createColumns(): DataTableColumns<SongsInfo> {
|
||||
// 使用 NSpace 渲染所有按钮
|
||||
return h(NSpace, { justify: 'end', size: 8, wrap: false }, () => buttons); // 增加间距,禁止换行
|
||||
},
|
||||
// --- 动态计算宽度 --- START
|
||||
/* width: (() => {
|
||||
let calculatedWidth = 20; // 基础内边距
|
||||
if (showLinkButton.value) calculatedWidth += 40; // 链接按钮宽度
|
||||
if (showListenButton.value) calculatedWidth += 40; // 试听按钮宽度
|
||||
if (props.isSelf) calculatedWidth += 80; // 编辑 + 删除按钮宽度
|
||||
if (props.extraButton) calculatedWidth += 40; // 额外按钮预估宽度
|
||||
return Math.max(calculatedWidth, props.isSelf ? 160 : 80); // 设置最小宽度防止太窄
|
||||
})(), */
|
||||
width: actionColumnWidth.value, // 使用计算属性
|
||||
// --- 动态计算宽度 --- END
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -763,6 +765,7 @@ onMounted(() => {
|
||||
item-style="display: flex; align-items: center;"
|
||||
size="small"
|
||||
>
|
||||
<template v-if="canShowListenSwitch">
|
||||
<NSwitch
|
||||
v-model:value="showListenButton"
|
||||
size="small"
|
||||
@@ -770,6 +773,8 @@ onMounted(() => {
|
||||
<NText style="font-size: 12px;">
|
||||
试听
|
||||
</NText>
|
||||
</template>
|
||||
<template v-if="canShowLinkSwitch">
|
||||
<NSwitch
|
||||
v-model:value="showLinkButton"
|
||||
size="small"
|
||||
@@ -777,6 +782,7 @@ onMounted(() => {
|
||||
<NText style="font-size: 12px;">
|
||||
链接
|
||||
</NText>
|
||||
</template>
|
||||
</NSpace>
|
||||
</NSpace>
|
||||
</NCard>
|
||||
|
||||
@@ -239,6 +239,17 @@ const orderColumn: DataTableColumns<OrderType> = [
|
||||
}, () => row.type === GoodsTypes.Physical ? '实体礼物' : '虚拟礼物')
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
key: 'remark',
|
||||
minWidth: 100,
|
||||
render: (row: OrderType) => {
|
||||
if (!row.remark) {
|
||||
return h(NText, { depth: 3, italic: true }, () => '无')
|
||||
}
|
||||
return h(NEllipsis, { style: { maxWidth: '100px' } }, () => row.remark)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
key: 'address',
|
||||
@@ -281,6 +292,7 @@ const orderColumn: DataTableColumns<OrderType> = [
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
render: (row: OrderType) => {
|
||||
return h(
|
||||
NButton,
|
||||
@@ -462,8 +474,6 @@ onMounted(() => {
|
||||
trigger="none"
|
||||
>
|
||||
<div class="order-detail-content">
|
||||
<!-- 用户视图 -->
|
||||
<template v-if="orderDetail.instanceOf === 'user'">
|
||||
<NDivider style="margin-top: 0">
|
||||
礼物快照
|
||||
<NTooltip>
|
||||
@@ -482,6 +492,23 @@ onMounted(() => {
|
||||
/>
|
||||
</NFlex>
|
||||
|
||||
<!-- 移动并修改备注信息 -->
|
||||
<template v-if="orderDetail.remark">
|
||||
<NAlert
|
||||
title="备注信息"
|
||||
type="info"
|
||||
style="margin-top: 16px; margin-bottom: 16px;"
|
||||
closable
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="Info24Filled" />
|
||||
</template>
|
||||
<NText>{{ orderDetail.remark }}</NText>
|
||||
</NAlert>
|
||||
</template>
|
||||
|
||||
<!-- 用户视图 -->
|
||||
<template v-if="orderDetail.instanceOf === 'user'">
|
||||
<!-- 虚拟礼物内容 -->
|
||||
<template v-if="orderDetail.type === GoodsTypes.Virtual">
|
||||
<NDivider>虚拟礼物内容</NDivider>
|
||||
@@ -531,14 +558,6 @@ onMounted(() => {
|
||||
|
||||
<!-- 主播视图 -->
|
||||
<template v-else-if="orderDetail.instanceOf === 'owner'">
|
||||
<NFlex justify="center">
|
||||
<PointGoodsItem
|
||||
v-if="currentGoods"
|
||||
class="goods-item"
|
||||
:goods="currentGoods"
|
||||
/>
|
||||
</NFlex>
|
||||
|
||||
<NDivider>订单状态管理</NDivider>
|
||||
|
||||
<!-- 虚拟礼物提示 -->
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
{
|
||||
label: () => h(RouterLink, { to: { name: 'user-checkin' } }, { default: () => '签到排行' }),
|
||||
key: 'user-checkin', icon: renderIcon(CheckmarkCircle24Filled),
|
||||
show: userInfo.value?.extra?.allowCheckInRanking
|
||||
show: userInfo.value?.extra?.enableFunctions.includes(FunctionTypes.CheckInRanking)
|
||||
},
|
||||
].filter(option => option.show !== false) as MenuOption[]; // 过滤掉 show 为 false 的菜单项
|
||||
}
|
||||
|
||||
@@ -633,12 +633,15 @@
|
||||
<NCheckbox :value="FunctionTypes.Schedule">
|
||||
日程
|
||||
</NCheckbox>
|
||||
<NCheckbox :value="FunctionTypes.SongRequest">
|
||||
<NCheckbox :value="FunctionTypes.LiveRequest">
|
||||
点歌
|
||||
</NCheckbox>
|
||||
<NCheckbox :value="FunctionTypes.Queue">
|
||||
排队
|
||||
</NCheckbox>
|
||||
<NCheckbox :value="FunctionTypes.CheckInRanking">
|
||||
签到排行
|
||||
</NCheckbox>
|
||||
</NCheckboxGroup>
|
||||
|
||||
<NDivider> 通知 </NDivider>
|
||||
|
||||
@@ -188,6 +188,7 @@ function exportData() {
|
||||
礼物总价: s.point,
|
||||
快递公司: s.expressCompany,
|
||||
快递单号: s.trackingNumber,
|
||||
备注: s.remark ?? '',
|
||||
创建时间: format(s.createAt, 'yyyy-MM-dd HH:mm:ss'),
|
||||
更新时间: s.updateAt ? format(s.updateAt, 'yyyy-MM-dd HH:mm:ss') : '未更新',
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ const defaultSettingPoint: Setting_Point = {
|
||||
maxBonusPoints: 0,
|
||||
allowSelfCheckIn: false,
|
||||
requireAuth: false,
|
||||
allowCheckInRanking: false
|
||||
}
|
||||
|
||||
// 响应式设置对象
|
||||
|
||||
@@ -76,12 +76,12 @@ const props = defineProps<{
|
||||
async function onUpdateFunctionEnable() {
|
||||
if (accountInfo.value.id) {
|
||||
const oldValue = JSON.parse(JSON.stringify(accountInfo.value.settings.enableFunctions))
|
||||
if (accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest)) {
|
||||
if (accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest)) {
|
||||
accountInfo.value.settings.enableFunctions = accountInfo.value.settings.enableFunctions.filter(
|
||||
(f) => f != FunctionTypes.SongRequest,
|
||||
(f) => f != FunctionTypes.LiveRequest,
|
||||
)
|
||||
} else {
|
||||
accountInfo.value.settings.enableFunctions.push(FunctionTypes.SongRequest)
|
||||
accountInfo.value.settings.enableFunctions.push(FunctionTypes.LiveRequest)
|
||||
}
|
||||
if (!accountInfo.value.settings.songRequest.orderPrefix) {
|
||||
accountInfo.value.settings.songRequest.orderPrefix = songRequest.defaultPrefix
|
||||
@@ -90,20 +90,20 @@ async function onUpdateFunctionEnable() {
|
||||
.then((data) => {
|
||||
if (data.code == 200) {
|
||||
message.success(
|
||||
`已${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}点播功能`,
|
||||
`已${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? '启用' : '禁用'}点播功能`,
|
||||
)
|
||||
} else {
|
||||
if (accountInfo.value.id) {
|
||||
accountInfo.value.settings.enableFunctions = oldValue
|
||||
}
|
||||
message.error(
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}失败: ${data.message}`,
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? '启用' : '禁用'}失败: ${data.message}`,
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error(
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}失败: ${err}`,
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? '启用' : '禁用'}失败: ${err}`,
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -158,11 +158,11 @@ onUnmounted(() => {
|
||||
<template>
|
||||
<NAlert
|
||||
v-if="accountInfo.id"
|
||||
:type="accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? 'success' : 'warning'"
|
||||
:type="accountInfo.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? 'success' : 'warning'"
|
||||
>
|
||||
启用弹幕点播功能
|
||||
<NSwitch
|
||||
:value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.SongRequest)"
|
||||
:value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.LiveRequest)"
|
||||
@update:value="onUpdateFunctionEnable"
|
||||
/>
|
||||
|
||||
@@ -215,7 +215,7 @@ onUnmounted(() => {
|
||||
<br>
|
||||
<NCard>
|
||||
<NTabs
|
||||
v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest)"
|
||||
v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.LiveRequest)"
|
||||
animated
|
||||
display-directive="show:lazy"
|
||||
>
|
||||
|
||||
@@ -24,7 +24,7 @@ const message = useMessage()
|
||||
|
||||
const enableSongRequest = computed({
|
||||
get: () => {
|
||||
return accountInfo.value?.settings?.enableFunctions?.includes(FunctionTypes.SongRequest) || false
|
||||
return accountInfo.value?.settings?.enableFunctions?.includes(FunctionTypes.LiveRequest) || false
|
||||
},
|
||||
set: async () => {
|
||||
await updateEnableFunctions()
|
||||
@@ -35,12 +35,12 @@ const enableSongRequest = computed({
|
||||
async function updateEnableFunctions() {
|
||||
if (accountInfo.value.id) {
|
||||
const oldValue = JSON.parse(JSON.stringify(accountInfo.value.settings.enableFunctions))
|
||||
if (accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest)) {
|
||||
if (accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest)) {
|
||||
accountInfo.value.settings.enableFunctions = accountInfo.value.settings.enableFunctions.filter(
|
||||
(f: number) => f != FunctionTypes.SongRequest,
|
||||
(f: number) => f != FunctionTypes.LiveRequest,
|
||||
)
|
||||
} else {
|
||||
accountInfo.value.settings.enableFunctions.push(FunctionTypes.SongRequest)
|
||||
accountInfo.value.settings.enableFunctions.push(FunctionTypes.LiveRequest)
|
||||
}
|
||||
if (!accountInfo.value.settings.songRequest.orderPrefix) {
|
||||
accountInfo.value.settings.songRequest.orderPrefix = liveRequest.defaultPrefix
|
||||
@@ -49,20 +49,20 @@ async function updateEnableFunctions() {
|
||||
.then((data) => {
|
||||
if (data.code == 200) {
|
||||
message.success(
|
||||
`已${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}点播功能`,
|
||||
`已${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? '启用' : '禁用'}点播功能`,
|
||||
)
|
||||
} else {
|
||||
if (accountInfo.value.id) {
|
||||
accountInfo.value.settings.enableFunctions = oldValue
|
||||
}
|
||||
message.error(
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}失败: ${data.message}`,
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? '启用' : '禁用'}失败: ${data.message}`,
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error(
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}失败: ${err}`,
|
||||
`点播功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.LiveRequest) ? '启用' : '禁用'}失败: ${err}`,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ const showAddressSelect = ref(false)
|
||||
const currentGoods = ref<ResponsePointGoodModel>() // 当前选中的礼物
|
||||
const buyCount = ref(1) // 购买数量
|
||||
const selectedAddress = ref<AddressInfo>() // 选中的地址
|
||||
const remark = ref('') // 新增:用于存储用户备注
|
||||
|
||||
// 筛选相关状态
|
||||
const selectedTag = ref<string>() // 选中的标签
|
||||
@@ -217,6 +218,7 @@ function resetBuyModalState() {
|
||||
selectedAddress.value = undefined
|
||||
buyCount.value = 1
|
||||
currentGoods.value = undefined
|
||||
remark.value = '' // 新增:重置备注
|
||||
}
|
||||
|
||||
// 处理模态框显示状态变化
|
||||
@@ -260,6 +262,7 @@ async function buyGoods() {
|
||||
goodsId: currentGoods.value?.id,
|
||||
count: buyCount.value,
|
||||
addressId: selectedAddress.value?.id ?? null, // 如果地址未选择,则传 null
|
||||
remark: remark.value, // 新增:将备注添加到请求中
|
||||
})
|
||||
|
||||
if (data.code === 200) {
|
||||
@@ -638,7 +641,7 @@ onMounted(async () => {
|
||||
/>
|
||||
|
||||
<!-- 兑换选项 (仅对实物或需要数量选择的礼物显示) -->
|
||||
<template v-if="currentGoods.type === GoodsTypes.Physical || (currentGoods.maxBuyCount ?? 1) > 1">
|
||||
<template v-if="currentGoods.type === GoodsTypes.Physical || (currentGoods.maxBuyCount ?? 1) > 1 || true">
|
||||
<NDivider style="margin-top: 12px; margin-bottom: 12px;">
|
||||
兑换选项
|
||||
</NDivider>
|
||||
@@ -689,6 +692,17 @@ onMounted(async () => {
|
||||
管理地址
|
||||
</NButton>
|
||||
</NFormItem>
|
||||
<!-- 备注输入 -->
|
||||
<NFormItem label="备注">
|
||||
<NInput
|
||||
v-model:value="remark"
|
||||
type="textarea"
|
||||
placeholder="可以在这里留下备注信息(可选)"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
maxlength="100"
|
||||
show-count
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ function loadMore() {
|
||||
clearable
|
||||
/>
|
||||
<NDivider />
|
||||
<LiveRequestOBS v-if="userInfo?.extra?.enableFunctions.includes(FunctionTypes.SongRequest)" />
|
||||
<LiveRequestOBS v-if="userInfo?.extra?.enableFunctions.includes(FunctionTypes.LiveRequest)" />
|
||||
</NSpace>
|
||||
</NCard>
|
||||
<NEmpty
|
||||
|
||||
Reference in New Issue
Block a user