Files
BYW-VoiceHub/app/composables/useSiteConfig.js
T
Henry_Du bd8df1f026
构建并部署 BYW VoiceHub / Preflight 语法与构建检查 (push) Failing after 6m31s
构建并部署 BYW VoiceHub / 构建并推送容器镜像 (push) Skipped
构建并部署 BYW VoiceHub / 部署到生产服务器 (push) Failing after 4s
feat(songs): 歌曲管理支持批量驳回、投稿留言自动审查与排期范围可见性过滤
- 新增 /api/admin/songs/batch-reject.post 批量驳回接口(事务清排期/投票/扣接纳数/黑名单去重/异步通知)
- requireSongAdmin 三角色校验 + createApiError 统一错误包装
- scheduleDaysBefore/After 四字段排期可见范围限制(开放 API 与公开排期接口三处缓存路径 + DB 条件过滤)
- submissionNoteAutoModeration 基于黑名单 KEYWORD/LANGUAGE/GENRE 自动判定留言 publicStatus,命中自动关闭 submissionNotePublic
- 更新 songs/request.post 与 songs/[id]/update.put 接入自动审查逻辑
2026-09-06 17:03:20 +08:00

166 lines
5.6 KiB
JavaScript

import { computed, ref, readonly } from 'vue'
const defaultSubmissionGuidelines = `1. 投稿时无需加入书名号
2. 除DJ外,其他类型歌曲均接收(包括小语种)
3. 禁止投递含有违规内容的歌曲
4. 点播的歌曲将由管理员进行审核
5. 审核通过后将安排在播放时段播出
6. 提交即表明我已阅读投稿须知并已知该歌曲有概率无法播出
7. 本系统仅提供音乐搜索和播放管理功能,不存储任何音乐文件。所有音乐内容均来自第三方音乐平台,版权归原平台及版权方所有。用户点歌时请确保遵守相关音乐平台的服务条款,尊重音乐作品版权。我们鼓励用户支持正版音乐,在官方平台购买和收听喜爱的音乐作品。
8. 最终解释权归广播站所有`
// 站点配置状态
const siteConfig = ref({
siteTitle: '',
siteLogoUrl: '',
schoolLogoHomeUrl: '',
schoolLogoPrintUrl: '',
siteDescription: '',
siteVersion: '',
submissionGuidelines: '',
icpNumber: '',
gonganNumber: '',
defaultTheme: null,
enabledThemes: null
})
const isLoaded = ref(false)
const isLoading = ref(false)
export const useSiteConfig = () => {
// 获取站点配置
const fetchSiteConfig = async () => {
if (isLoading.value) return
try {
isLoading.value = true
const response = await fetch('/api/site-config')
if (!response.ok) {
throw new Error('获取站点配置失败')
}
const data = await response.json()
siteConfig.value = data
isLoaded.value = true
} catch (error) {
console.error('获取站点配置失败:', error)
// 使用默认配置
siteConfig.value = {
siteTitle: '校园广播站点歌系统',
siteLogoUrl: '/images/site-logo.png',
schoolLogoHomeUrl: '/images/school-logo-white.png',
schoolLogoPrintUrl: '/images/school-logo-transparent.png',
siteDescription: '校园广播站点歌系统 - 让你的声音被听见',
siteVersion: '',
submissionGuidelines: defaultSubmissionGuidelines,
icpNumber: '',
gonganNumber: '',
enableReplayRequests: false,
enableCollaborativeSubmission: true,
enableSubmissionRemarks: false,
defaultTheme: 'System',
enabledThemes: '["System","ClassicDark","ClassicLight","ModernLight"]'
}
isLoaded.value = true
} finally {
isLoading.value = false
}
}
// 计算属性
const siteTitle = computed(() => siteConfig.value.siteTitle || '校园广播站点歌系统')
const logoUrl = computed(() => {
const url = siteConfig.value.siteLogoUrl
return (!url || url === '/favicon.ico') ? '/images/site-logo.png' : url
})
const schoolLogoHomeUrl = computed(() => {
const raw = (siteConfig.value.schoolLogoHomeUrl || '').trim()
const fallback = '/images/school-logo-white.png'
if (!raw) return fallback
if (raw === '/images/school-logo-white.png' || raw === '/images/school-logo-black.png') return fallback
return raw
})
const schoolLogoPrintUrl = computed(() => siteConfig.value.schoolLogoPrintUrl || '/images/school-logo.png')
const description = computed(
() => siteConfig.value.siteDescription || '校园广播站点歌系统 - 让你的声音被听见'
)
const siteVersion = computed(() => (siteConfig.value.siteVersion || '').trim())
const guidelines = computed(
() => siteConfig.value.submissionGuidelines || defaultSubmissionGuidelines
)
const icp = computed(() => siteConfig.value.icpNumber || '')
const gonganNumber = computed(() => siteConfig.value.gonganNumber || '')
const enableReplayRequests = computed(() => siteConfig.value.enableReplayRequests || false)
const enableCollaborativeSubmission = computed(
() => siteConfig.value.enableCollaborativeSubmission !== false
)
const enableSubmissionRemarks = computed(() => siteConfig.value.enableSubmissionRemarks === true)
const smtpEnabled = computed(() => !!siteConfig.value.smtpEnabled)
function parseEnabledThemes(raw) {
if (Array.isArray(raw)) return raw.filter(Boolean)
if (typeof raw === 'string') {
const s = raw.trim()
if (!s) return []
if (s.startsWith('[') || s.startsWith('{')) {
try {
const parsed = JSON.parse(s)
if (Array.isArray(parsed)) return parsed.filter(Boolean)
if (parsed && Array.isArray(parsed.items)) return parsed.items.filter(Boolean)
} catch (_) {
// fallback to comma split
}
}
return s.split(',').map((x) => x.trim()).filter(Boolean)
}
return []
}
const defaultTheme = computed(() =>
typeof siteConfig.value.defaultTheme === 'string' && siteConfig.value.defaultTheme
? siteConfig.value.defaultTheme
: null
)
const enabledThemes = computed(() => parseEnabledThemes(siteConfig.value.enabledThemes))
// 初始化配置(仅在客户端执行)
const initSiteConfig = async () => {
if (typeof window !== 'undefined' && !isLoaded.value) {
await fetchSiteConfig()
}
}
// 刷新配置
const refreshSiteConfig = async () => {
isLoaded.value = false
await fetchSiteConfig()
}
return {
siteConfig: readonly(siteConfig),
isLoaded: readonly(isLoaded),
isLoading: readonly(isLoading),
siteTitle,
logoUrl,
schoolLogoHomeUrl,
schoolLogoPrintUrl,
description,
siteVersion,
guidelines,
icp,
gonganNumber,
enableReplayRequests,
enableCollaborativeSubmission,
enableSubmissionRemarks,
smtpEnabled,
defaultTheme,
enabledThemes,
fetchSiteConfig,
initSiteConfig,
refreshSiteConfig
}
}