feat: 添加简单模式功能

新增简单模式设置,适合个人使用场景:
- 隐藏多用户管理相关菜单(用户管理、兑换码等)
- 自动关闭用户注册功能
- 管理员并发数自动设为无限制(99999)
- 侧边栏根据模式动态调整菜单项

同时优化分组页面的"专属分组"功能,添加帮助提示说明使用场景
This commit is contained in:
shaw
2025-12-28 22:19:18 +08:00
parent fb9d087838
commit 7d4b7deea9
16 changed files with 378 additions and 90 deletions

View File

@@ -153,6 +153,58 @@
</div>
</div>
<!-- Usage Mode Settings -->
<div class="card">
<div class="border-b border-gray-100 px-6 py-4 dark:border-dark-700">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
{{ t('admin.settings.usageMode.title') }}
</h2>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
{{ t('admin.settings.usageMode.description') }}
</p>
</div>
<div class="space-y-5 p-6">
<!-- Simple Mode Toggle -->
<div class="flex items-center justify-between">
<div>
<label class="font-medium text-gray-900 dark:text-white">
{{ t('admin.settings.usageMode.simpleMode') }}
</label>
<p class="text-sm text-gray-500 dark:text-gray-400">
{{ t('admin.settings.usageMode.simpleModeHint') }}
</p>
</div>
<Toggle
:model-value="form.simple_mode"
@update:model-value="onSimpleModeToggle"
/>
</div>
<!-- Warning when simple mode is enabled -->
<div
v-if="form.simple_mode"
class="rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-800 dark:bg-amber-900/20"
>
<div class="flex items-start">
<svg
class="mt-0.5 h-5 w-5 flex-shrink-0 text-amber-500"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
clip-rule="evenodd"
/>
</svg>
<p class="ml-3 text-sm text-amber-700 dark:text-amber-300">
{{ t('admin.settings.usageMode.simpleModeWarning') }}
</p>
</div>
</div>
</div>
</div>
<!-- Registration Settings -->
<div class="card">
<div class="border-b border-gray-100 px-6 py-4 dark:border-dark-700">
@@ -706,6 +758,19 @@
</div>
</form>
</div>
<!-- Simple Mode Confirmation Dialog -->
<ConfirmDialog
:show="showSimpleModeConfirm"
:title="t('admin.settings.usageMode.confirmTitle')"
:message="pendingSimpleModeValue
? t('admin.settings.usageMode.confirmEnableMessage')
: t('admin.settings.usageMode.confirmDisableMessage')"
:confirm-text="t('common.confirm')"
:cancel-text="t('common.cancel')"
@confirm="confirmSimpleModeChange"
@cancel="cancelSimpleModeChange"
/>
</AppLayout>
</template>
@@ -716,6 +781,7 @@ import { adminAPI } from '@/api'
import type { SystemSettings } from '@/api/admin/settings'
import AppLayout from '@/components/layout/AppLayout.vue'
import Toggle from '@/components/common/Toggle.vue'
import ConfirmDialog from '@/components/common/ConfirmDialog.vue'
import { useAppStore } from '@/stores'
const { t } = useI18n()
@@ -728,6 +794,10 @@ const sendingTestEmail = ref(false)
const testEmailAddress = ref('')
const logoError = ref('')
// Simple mode confirmation dialog
const showSimpleModeConfirm = ref(false)
const pendingSimpleModeValue = ref(false)
// Admin API Key 状态
const adminApiKeyLoading = ref(true)
const adminApiKeyExists = ref(false)
@@ -756,7 +826,9 @@ const form = reactive<SystemSettings>({
// Cloudflare Turnstile
turnstile_enabled: false,
turnstile_site_key: '',
turnstile_secret_key: ''
turnstile_secret_key: '',
// Usage mode
simple_mode: false
})
function handleLogoUpload(event: Event) {
@@ -827,6 +899,40 @@ async function saveSettings() {
}
}
// Simple mode toggle handlers
function onSimpleModeToggle(value: boolean) {
pendingSimpleModeValue.value = value
showSimpleModeConfirm.value = true
}
async function confirmSimpleModeChange() {
showSimpleModeConfirm.value = false
form.simple_mode = pendingSimpleModeValue.value
saving.value = true
try {
await adminAPI.settings.updateSettings(form)
await appStore.fetchPublicSettings(true)
appStore.showSuccess(t('admin.settings.settingsSaved'))
// Reload page to apply menu changes
setTimeout(() => {
window.location.reload()
}, 500)
} catch (error: any) {
// Revert on error
form.simple_mode = !pendingSimpleModeValue.value
appStore.showError(
t('admin.settings.failedToSave') + ': ' + (error.message || t('common.unknownError'))
)
} finally {
saving.value = false
}
}
function cancelSimpleModeChange() {
showSimpleModeConfirm.value = false
}
async function testSmtpConnection() {
testingSmtp.value = true
try {