1. layout(管理控制台 dashboard.vue): main bg-[#09090b] text-zinc-100 → bg-[#f8fafc] text-zinc-900; header bg-zinc-950/60 border-zinc-800 → bg-white/80 border-zinc-200; 移动菜单按钮/新手引导按钮 text-zinc-300/400 hover:bg-zinc-800 → text-zinc-600 hover:bg-zinc-100 border-zinc-200
2. Admin/Sidebar.vue: bg-[#09090b] border-zinc-800 → bg-white border-zinc-200 + shadow-sm; 标题 text-zinc-100 → 900; activeTab bg-blue-600/10 text-blue-400 → bg-blue-50 text-blue-700 border-blue-200; 未选中 text-zinc-500 hover:text-zinc-200 hover:bg-zinc-800/40 → text-zinc-600 hover:text-zinc-900 hover:bg-zinc-100; 用户卡 avatar/首字母 bg-white/70 border-zinc-200 + 退出按钮 hover:bg-red-50 text-red-600
3. 批量 33 个 Admin 组件硬编码深色原子类 1414 处替换(bg-zinc-9xx / border-zinc-8xx / text-zinc-100,200,300 / shadow-black/ -> 对应 light 版本) + style 块原生 CSS rgba(255,255,255,x) 16 处改为 rgba(0,0,0,x) / var 浅色主题 + 硬编码 bg-[#0c0c0e] / border-white/10 / color:white / surface-primary fallback 对应浅色修正
4. 二轮批量追加: bg-zinc-950 + opacity 变体(80/60/50/40/30/20/10) 共 431 处 → bg-white 对应 opacity 版本;placeholder:text-zinc-800 → 500;text-blue/red/emerald/amber/rose/purple 400 版 → 700/600 深浅一致版;border color /500 /30 → 200;focus:ring /20 → /30;shadow color 阴影降低强度
5. hover:text-white 扫尾: 13 处 DataAnalysisPanel/DatabaseManager/NotificationSender/SemesterManager/SongManagement/UserSongsModal hover 文本从 white → zinc-900;按钮三态从 hover:bg-*600 白字 → hover:bg-*-100/200 对应深字色,和前台 indigo/浅色体系保持一致
6. BlacklistManager 前台可见提示 💡→ <Icon lightbulb amber-600 size=13>;ChangelogManager 徽章色从 emerald-300/blue-300/zinc-400 → emerald-700/blue-700/zinc-600 可读;Icon.vue 新增 lightbulb 分支 stroke 图标
7. 受影响文件: dashboard.vue + Sidebar.vue + Icon.vue + Admin/* (33个组件共 1874 处批量替换 + 20 处手工精细化修正)
549 lines
20 KiB
Vue
549 lines
20 KiB
Vue
<template>
|
||
<div class="max-w-[1200px] mx-auto space-y-6 pb-24 px-2">
|
||
<!-- 顶部标题栏 -->
|
||
<div class="flex flex-col md:flex-row md:items-end justify-between gap-4">
|
||
<div>
|
||
<h2 class="text-2xl font-black text-zinc-900 tracking-tight">站点配置</h2>
|
||
<p class="text-xs text-zinc-500 mt-1 font-medium">
|
||
管理站点全局属性、视觉识别、点歌逻辑及系统安全策略
|
||
</p>
|
||
</div>
|
||
<div class="flex gap-3">
|
||
<button
|
||
:disabled="loading || saving"
|
||
class="flex items-center gap-2 px-5 py-2 bg-white border border-zinc-200 hover:border-zinc-200 text-zinc-400 text-xs font-bold rounded-xl transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||
@click="resetForm"
|
||
>
|
||
<RotateCcw :size="14" /> 重置
|
||
</button>
|
||
<button
|
||
:disabled="loading || saving"
|
||
class="flex items-center gap-2 px-8 py-2 bg-blue-600 hover:bg-blue-500 text-white text-xs font-black rounded-xl shadow-lg shadow-blue-900/20 transition-all active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed"
|
||
@click="saveConfig"
|
||
>
|
||
<template v-if="saving">
|
||
<div
|
||
class="w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin"
|
||
/>
|
||
保存中...
|
||
</template>
|
||
<template v-else-if="saveSuccess"> <CheckCircle2 :size="14" /> 已保存 </template>
|
||
<template v-else> <Save :size="14" /> 保存配置 </template>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="loading" class="flex flex-col items-center justify-center py-20">
|
||
<div
|
||
class="w-8 h-8 border-4 border-zinc-200 border-t-blue-500 rounded-full animate-spin mb-4"
|
||
/>
|
||
<p class="text-zinc-500 text-sm">加载配置中...</p>
|
||
</div>
|
||
|
||
<div v-else class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||
<!-- 基础信息 -->
|
||
<section :class="cardClass">
|
||
<h3
|
||
class="text-sm font-black text-zinc-900 uppercase tracking-widest flex items-center gap-2 border-b border-zinc-200 pb-4"
|
||
>
|
||
<Globe :size="16" class="text-blue-500" /> 基础信息
|
||
</h3>
|
||
<div class="space-y-4">
|
||
<div>
|
||
<label :class="labelClass">站点标题</label>
|
||
<input
|
||
v-model="formData.siteTitle"
|
||
type="text"
|
||
placeholder="请输入站点标题"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
<div>
|
||
<label :class="labelClass">备案号 (ICP)</label>
|
||
<input
|
||
v-model="formData.icpNumber"
|
||
type="text"
|
||
placeholder="请输入备案号"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
<div>
|
||
<label :class="labelClass">公安联网备案号</label>
|
||
<input
|
||
v-model="formData.gonganNumber"
|
||
type="text"
|
||
placeholder="请输入公安备案号 (如:陕公网安备61011302001964号)"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
<div>
|
||
<label :class="labelClass">站点描述</label>
|
||
<textarea
|
||
v-model="formData.siteDescription"
|
||
:rows="3"
|
||
placeholder="请输入站点描述"
|
||
:class="[inputClass, 'resize-none']"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label :class="labelClass">站点版本号</label>
|
||
<input
|
||
v-model="formData.siteVersion"
|
||
type="text"
|
||
placeholder="如:v2.4.1 或 2026.04"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 视觉识别 -->
|
||
<section :class="cardClass">
|
||
<h3
|
||
class="text-sm font-black text-zinc-900 uppercase tracking-widest flex items-center gap-2 border-b border-zinc-200 pb-4"
|
||
>
|
||
<ImageIcon :size="16" class="text-purple-500" /> 视觉识别
|
||
</h3>
|
||
<div class="space-y-4">
|
||
<div>
|
||
<label :class="labelClass">站点 Logo URL</label>
|
||
<input
|
||
v-model="formData.siteLogoUrl"
|
||
type="text"
|
||
placeholder="请输入Logo图片URL"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
<div>
|
||
<label :class="labelClass">首页学校 Logo URL (大尺寸)</label>
|
||
<input
|
||
v-model="formData.schoolLogoHomeUrl"
|
||
type="text"
|
||
placeholder="请输入首页学校Logo URL"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
<div>
|
||
<label :class="labelClass">打印排期 Logo URL (小尺寸)</label>
|
||
<input
|
||
v-model="formData.schoolLogoPrintUrl"
|
||
type="text"
|
||
placeholder="请输入打印页学校Logo URL"
|
||
:class="inputClass"
|
||
>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 投稿须知 -->
|
||
<section
|
||
class="lg:col-span-2 bg-zinc-50/40 border border-zinc-200 rounded-2xl p-6 space-y-6"
|
||
>
|
||
<h3
|
||
class="text-sm font-black text-zinc-900 uppercase tracking-widest flex items-center gap-2 border-b border-zinc-200 pb-4"
|
||
>
|
||
<FileText :size="16" class="text-emerald-500" /> 投稿须知
|
||
</h3>
|
||
<textarea
|
||
v-model="formData.submissionGuidelines"
|
||
:rows="6"
|
||
placeholder="请输入投稿须知内容"
|
||
:class="[inputClass, 'font-mono text-xs leading-relaxed min-h-[150px]']"
|
||
/>
|
||
</section>
|
||
|
||
<!-- 投稿逻辑设置 -->
|
||
<section :class="cardClass">
|
||
<h3
|
||
class="text-sm font-black text-zinc-900 uppercase tracking-widest flex items-center gap-2 border-b border-zinc-200 pb-4"
|
||
>
|
||
<Settings2 :size="16" class="text-amber-500" /> 投稿逻辑设置
|
||
</h3>
|
||
<div class="space-y-6">
|
||
<div
|
||
class="flex items-center justify-between p-3 bg-white/70 border border-zinc-200 rounded-xl"
|
||
>
|
||
<div>
|
||
<p class="text-xs font-bold text-zinc-700">启用联合投稿</p>
|
||
<p class="text-[10px] text-zinc-500 mt-0.5">允许用户添加联合投稿人并发起协作投稿</p>
|
||
</div>
|
||
<input
|
||
v-model="formData.enableCollaborativeSubmission"
|
||
type="checkbox"
|
||
class="w-5 h-5 rounded border-zinc-200 bg-white accent-blue-600 cursor-pointer"
|
||
>
|
||
</div>
|
||
|
||
<div
|
||
class="flex items-center justify-between p-3 bg-white/70 border border-zinc-200 rounded-xl"
|
||
>
|
||
<div>
|
||
<p class="text-xs font-bold text-zinc-700">启用投稿备注留言</p>
|
||
<p class="text-[10px] text-zinc-500 mt-0.5">允许用户在投稿时附加公开或仅管理员可见的备注</p>
|
||
</div>
|
||
<input
|
||
v-model="formData.enableSubmissionRemarks"
|
||
type="checkbox"
|
||
class="w-5 h-5 rounded border-zinc-200 bg-white accent-blue-600 cursor-pointer"
|
||
>
|
||
</div>
|
||
|
||
<div
|
||
class="flex items-center justify-between p-3 bg-white/70 border border-zinc-200 rounded-xl"
|
||
>
|
||
<div>
|
||
<p class="text-xs font-bold text-zinc-700">启用重播申请</p>
|
||
<p class="text-[10px] text-zinc-500 mt-0.5">允许用户对本学期已播放过的歌曲再次申请</p>
|
||
</div>
|
||
<input
|
||
v-model="formData.enableReplayRequests"
|
||
type="checkbox"
|
||
class="w-5 h-5 rounded border-zinc-200 bg-white accent-blue-600 cursor-pointer"
|
||
>
|
||
</div>
|
||
|
||
<div class="space-y-4">
|
||
<div
|
||
class="flex items-center justify-between p-3 bg-white/70 border border-zinc-200 rounded-xl"
|
||
>
|
||
<div>
|
||
<p class="text-xs font-bold text-zinc-700">启用投稿限额</p>
|
||
<p class="text-[10px] text-zinc-500 mt-0.5">限制单个用户的点歌频率</p>
|
||
</div>
|
||
<input
|
||
v-model="formData.enableSubmissionLimit"
|
||
type="checkbox"
|
||
class="w-5 h-5 rounded border-zinc-200 bg-white accent-blue-600 cursor-pointer"
|
||
>
|
||
</div>
|
||
|
||
<div v-if="formData.enableSubmissionLimit" class="space-y-4">
|
||
<div class="grid grid-cols-3 gap-2 p-1 bg-white border border-zinc-200 rounded-xl">
|
||
<button
|
||
:class="[
|
||
'py-2 rounded-lg text-[10px] font-black uppercase tracking-widest transition-all',
|
||
currentLimitType === 'daily'
|
||
? 'bg-zinc-100 text-blue-700 shadow-sm'
|
||
: 'text-zinc-600 hover:text-zinc-400'
|
||
]"
|
||
@click="handleLimitTypeChange('daily')"
|
||
>
|
||
每日限额
|
||
</button>
|
||
<button
|
||
:class="[
|
||
'py-2 rounded-lg text-[10px] font-black uppercase tracking-widest transition-all',
|
||
currentLimitType === 'weekly'
|
||
? 'bg-zinc-100 text-blue-700 shadow-sm'
|
||
: 'text-zinc-600 hover:text-zinc-400'
|
||
]"
|
||
@click="handleLimitTypeChange('weekly')"
|
||
>
|
||
每周限额
|
||
</button>
|
||
<button
|
||
:class="[
|
||
'py-2 rounded-lg text-[10px] font-black uppercase tracking-widest transition-all',
|
||
currentLimitType === 'monthly'
|
||
? 'bg-zinc-100 text-blue-700 shadow-sm'
|
||
: 'text-zinc-600 hover:text-zinc-400'
|
||
]"
|
||
@click="handleLimitTypeChange('monthly')"
|
||
>
|
||
每月限额
|
||
</button>
|
||
</div>
|
||
|
||
<div>
|
||
<label :class="labelClass"
|
||
>{{ currentLimitType === 'daily' ? '单日' : (currentLimitType === 'weekly' ? '单周' : '单月') }}投稿上限</label
|
||
>
|
||
<div class="relative">
|
||
<input
|
||
v-model.number="currentLimitValue"
|
||
type="number"
|
||
min="0"
|
||
:class="inputClass"
|
||
>
|
||
<span
|
||
class="absolute right-4 top-1/2 -translate-y-1/2 text-[10px] font-black text-zinc-700 uppercase"
|
||
>首 / 人</span
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 安全与隐私设置 -->
|
||
<section :class="cardClass">
|
||
<h3
|
||
class="text-sm font-black text-zinc-900 uppercase tracking-widest flex items-center gap-2 border-b border-zinc-200 pb-4"
|
||
>
|
||
<Shield :size="16" class="text-rose-500" /> 安全与隐私设置
|
||
</h3>
|
||
<div class="space-y-4">
|
||
<div class="p-4 bg-white/70 border border-zinc-200 rounded-xl space-y-4">
|
||
<div class="flex items-start gap-4">
|
||
<div class="shrink-0 pt-0.5">
|
||
<input
|
||
id="show-keywords"
|
||
v-model="formData.showBlacklistKeywords"
|
||
type="checkbox"
|
||
class="w-4 h-4 rounded border-zinc-200 bg-white accent-blue-600 cursor-pointer"
|
||
>
|
||
</div>
|
||
<label for="show-keywords" class="cursor-pointer">
|
||
<p class="text-xs font-bold text-zinc-700">显示黑名单具体关键词</p>
|
||
<p class="text-[10px] text-zinc-500 mt-1 leading-relaxed">
|
||
开启后,在投稿命中黑名单时将明确提示冲突关键词;关闭则仅提示“包含关键词”。
|
||
</p>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="p-4 bg-white/70 border border-zinc-200 rounded-xl space-y-4">
|
||
<div class="flex items-start gap-4">
|
||
<div class="shrink-0 pt-0.5">
|
||
<input
|
||
id="hide-students"
|
||
v-model="formData.hideStudentInfo"
|
||
type="checkbox"
|
||
class="w-4 h-4 rounded border-zinc-200 bg-white accent-blue-600 cursor-pointer"
|
||
>
|
||
</div>
|
||
<label for="hide-students" class="cursor-pointer">
|
||
<p class="text-xs font-bold text-zinc-700">隐藏学生详细信息</p>
|
||
<p class="text-[10px] text-zinc-500 mt-1 leading-relaxed">
|
||
开启后,非管理员用户在前端点歌列表、排期预览中将无法查看投稿学生的完整学号与真实姓名。
|
||
</p>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
class="p-4 bg-blue-500/5 border border-blue-500/10 rounded-xl flex items-start gap-3"
|
||
>
|
||
<AlertCircle class="text-blue-500 shrink-0 mt-0.5" :size="14" />
|
||
<p class="text-[10px] text-zinc-500 leading-normal">
|
||
站点基础配置在保存后将立即对所有终端生效。请在修改关键业务逻辑(如投稿限额)前确保已知晓对现有用户的影响。
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, onMounted, ref } from 'vue'
|
||
import {
|
||
Globe,
|
||
ImageIcon,
|
||
FileText,
|
||
Settings2,
|
||
Shield,
|
||
Save,
|
||
RotateCcw,
|
||
CheckCircle2,
|
||
AlertCircle
|
||
} from '@lucide/vue'
|
||
import { useToast } from '~/composables/useToast'
|
||
|
||
const { showToast: showNotification } = useToast()
|
||
|
||
const loading = ref(true)
|
||
const saving = ref(false)
|
||
const saveSuccess = ref(false)
|
||
|
||
// 样式类常量
|
||
const inputClass =
|
||
'w-full bg-white border border-zinc-200 rounded-xl px-4 py-2.5 text-sm text-zinc-700 focus:outline-none focus:border-blue-200 transition-all placeholder:text-zinc-500'
|
||
const labelClass = 'text-[10px] font-black text-zinc-600 uppercase tracking-widest px-1 block mb-2'
|
||
const cardClass = 'bg-zinc-50/40 border border-zinc-200 rounded-2xl p-6 shadow-xl space-y-6'
|
||
|
||
const defaultSubmissionGuidelines = `1. 投稿时无需加入书名号
|
||
2. 除DJ外,其他类型歌曲均接收(包括小语种)
|
||
3. 禁止投递含有违规内容的歌曲
|
||
4. 点播的歌曲将由管理员进行审核
|
||
5. 审核通过后将安排在播放时段播出
|
||
6. 提交即表明我已阅读投稿须知并已知该歌曲有概率无法播出
|
||
7. 本系统仅提供音乐搜索和播放管理功能,不存储任何音乐文件。所有音乐内容均来自第三方音乐平台,版权归原平台及版权方所有。用户点歌时请确保遵守相关音乐平台的服务条款,尊重音乐作品版权。我们鼓励用户支持正版音乐,在官方平台购买和收听喜爱的音乐作品。
|
||
8. 最终解释权归广播站所有`
|
||
|
||
const formData = ref({
|
||
siteTitle: '',
|
||
siteLogoUrl: '',
|
||
schoolLogoHomeUrl: '',
|
||
schoolLogoPrintUrl: '',
|
||
siteDescription: '',
|
||
siteVersion: '',
|
||
submissionGuidelines: '',
|
||
icpNumber: '',
|
||
gonganNumber: '',
|
||
enableCollaborativeSubmission: true,
|
||
enableSubmissionRemarks: false,
|
||
enableReplayRequests: false,
|
||
enableSubmissionLimit: false,
|
||
dailySubmissionLimit: 5,
|
||
weeklySubmissionLimit: null,
|
||
monthlySubmissionLimit: null,
|
||
showBlacklistKeywords: false,
|
||
hideStudentInfo: true
|
||
})
|
||
|
||
const originalData = ref({})
|
||
|
||
// 当前限额类型和值的快捷访问
|
||
const currentLimitType = computed(() => {
|
||
if (formData.value.monthlySubmissionLimit !== null) return 'monthly'
|
||
return formData.value.weeklySubmissionLimit !== null ? 'weekly' : 'daily'
|
||
})
|
||
|
||
const currentLimitValue = computed({
|
||
get: () => {
|
||
if (currentLimitType.value === 'monthly') return formData.value.monthlySubmissionLimit
|
||
return currentLimitType.value === 'daily'
|
||
? formData.value.dailySubmissionLimit
|
||
: formData.value.weeklySubmissionLimit
|
||
},
|
||
set: (val) => {
|
||
if (currentLimitType.value === 'monthly') {
|
||
formData.value.monthlySubmissionLimit = val
|
||
} else if (currentLimitType.value === 'daily') {
|
||
formData.value.dailySubmissionLimit = val
|
||
} else {
|
||
formData.value.weeklySubmissionLimit = val
|
||
}
|
||
}
|
||
})
|
||
|
||
// 加载配置
|
||
const loadConfig = async () => {
|
||
try {
|
||
loading.value = true
|
||
const response = await fetch('/api/admin/system-settings', {
|
||
credentials: 'include'
|
||
})
|
||
|
||
if (!response.ok) throw new Error('获取配置失败')
|
||
|
||
const data = await response.json()
|
||
|
||
formData.value = {
|
||
siteTitle: data.siteTitle || '',
|
||
siteLogoUrl: data.siteLogoUrl || '',
|
||
schoolLogoHomeUrl: data.schoolLogoHomeUrl || '',
|
||
schoolLogoPrintUrl: data.schoolLogoPrintUrl || '',
|
||
siteDescription: data.siteDescription || '',
|
||
siteVersion: data.siteVersion || '',
|
||
submissionGuidelines: data.submissionGuidelines || defaultSubmissionGuidelines,
|
||
icpNumber: data.icpNumber || '',
|
||
gonganNumber: data.gonganNumber || '',
|
||
enableCollaborativeSubmission: data.enableCollaborativeSubmission !== false,
|
||
enableSubmissionRemarks: !!data.enableSubmissionRemarks,
|
||
enableReplayRequests: !!data.enableReplayRequests,
|
||
enableSubmissionLimit: !!data.enableSubmissionLimit,
|
||
dailySubmissionLimit: data.dailySubmissionLimit ?? 5,
|
||
weeklySubmissionLimit: data.weeklySubmissionLimit ?? null,
|
||
monthlySubmissionLimit: data.monthlySubmissionLimit ?? null,
|
||
showBlacklistKeywords: !!data.showBlacklistKeywords,
|
||
hideStudentInfo: data.hideStudentInfo ?? true
|
||
}
|
||
|
||
originalData.value = JSON.parse(JSON.stringify(formData.value))
|
||
} catch (error) {
|
||
console.error('加载配置失败:', error)
|
||
showNotification('加载配置失败', 'error')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 保存配置
|
||
const saveConfig = async () => {
|
||
try {
|
||
saving.value = true
|
||
const configToSave = {
|
||
...formData.value,
|
||
siteTitle: (formData.value.siteTitle || '').trim() || '校园广播站点歌系统',
|
||
siteLogoUrl: (formData.value.siteLogoUrl || '').trim() || '/images/site-logo.png',
|
||
siteVersion: (formData.value.siteVersion || '').trim() || null,
|
||
submissionGuidelines:
|
||
(formData.value.submissionGuidelines || '').trim() || defaultSubmissionGuidelines,
|
||
// 确保根据限额类型处理空值
|
||
dailySubmissionLimit:
|
||
currentLimitType.value === 'daily' ? formData.value.dailySubmissionLimit : null,
|
||
weeklySubmissionLimit:
|
||
currentLimitType.value === 'weekly' ? formData.value.weeklySubmissionLimit : null,
|
||
monthlySubmissionLimit:
|
||
currentLimitType.value === 'monthly' ? formData.value.monthlySubmissionLimit : null
|
||
}
|
||
|
||
const response = await fetch('/api/admin/system-settings', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
credentials: 'include',
|
||
body: JSON.stringify(configToSave)
|
||
})
|
||
|
||
if (!response.ok) throw new Error('保存配置失败')
|
||
|
||
saveSuccess.value = true
|
||
originalData.value = JSON.parse(JSON.stringify(formData.value))
|
||
showNotification('配置保存成功!', 'success')
|
||
|
||
setTimeout(() => {
|
||
saveSuccess.value = false
|
||
}, 3000)
|
||
} catch (error) {
|
||
console.error('保存配置失败:', error)
|
||
showNotification('保存配置失败,请重试', 'error')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
|
||
// 处理限额类型变化
|
||
const handleLimitTypeChange = (type) => {
|
||
const limits = {
|
||
daily: { key: 'dailySubmissionLimit', default: 5 },
|
||
weekly: { key: 'weeklySubmissionLimit', default: 20 },
|
||
monthly: { key: 'monthlySubmissionLimit', default: 50 }
|
||
}
|
||
|
||
// 将非当前类型的限额设为 null
|
||
Object.keys(limits).forEach((limitType) => {
|
||
if (limitType !== type) {
|
||
formData.value[limits[limitType].key] = null
|
||
}
|
||
})
|
||
|
||
// 如果当前类型的限额为 null,则设置默认值
|
||
const targetLimit = limits[type]
|
||
if (formData.value[targetLimit.key] === null) {
|
||
formData.value[targetLimit.key] = targetLimit.default
|
||
}
|
||
}
|
||
|
||
// 重置表单
|
||
const resetForm = () => {
|
||
formData.value = JSON.parse(JSON.stringify(originalData.value))
|
||
}
|
||
|
||
onMounted(loadConfig)
|
||
</script>
|
||
|
||
<style scoped>
|
||
input::-webkit-outer-spin-button,
|
||
input::-webkit-inner-spin-button {
|
||
-webkit-appearance: none;
|
||
margin: 0;
|
||
}
|
||
|
||
input[type='number'] {
|
||
-moz-appearance: textfield;
|
||
}
|
||
</style>
|