mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 09:38:02 +00:00
feat: 支持隐藏后台登录入口按钮
This commit is contained in:
@@ -5396,6 +5396,7 @@ router.get('/oem-settings', async (req, res) => {
|
|||||||
siteName: 'Claude Relay Service',
|
siteName: 'Claude Relay Service',
|
||||||
siteIcon: '',
|
siteIcon: '',
|
||||||
siteIconData: '', // Base64编码的图标数据
|
siteIconData: '', // Base64编码的图标数据
|
||||||
|
showAdminButton: true, // 是否显示管理后台按钮
|
||||||
updatedAt: new Date().toISOString()
|
updatedAt: new Date().toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5425,7 +5426,7 @@ router.get('/oem-settings', async (req, res) => {
|
|||||||
// 更新OEM设置
|
// 更新OEM设置
|
||||||
router.put('/oem-settings', authenticateAdmin, async (req, res) => {
|
router.put('/oem-settings', authenticateAdmin, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { siteName, siteIcon, siteIconData } = req.body
|
const { siteName, siteIcon, siteIconData, showAdminButton } = req.body
|
||||||
|
|
||||||
// 验证输入
|
// 验证输入
|
||||||
if (!siteName || typeof siteName !== 'string' || siteName.trim().length === 0) {
|
if (!siteName || typeof siteName !== 'string' || siteName.trim().length === 0) {
|
||||||
@@ -5456,6 +5457,7 @@ router.put('/oem-settings', authenticateAdmin, async (req, res) => {
|
|||||||
siteName: siteName.trim(),
|
siteName: siteName.trim(),
|
||||||
siteIcon: (siteIcon || '').trim(),
|
siteIcon: (siteIcon || '').trim(),
|
||||||
siteIconData: (siteIconData || '').trim(), // Base64数据
|
siteIconData: (siteIconData || '').trim(), // Base64数据
|
||||||
|
showAdminButton: showAdminButton !== false, // 默认为true
|
||||||
updatedAt: new Date().toISOString()
|
updatedAt: new Date().toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
siteName: 'Claude Relay Service',
|
siteName: 'Claude Relay Service',
|
||||||
siteIcon: '',
|
siteIcon: '',
|
||||||
siteIconData: '',
|
siteIconData: '',
|
||||||
|
showAdminButton: true, // 控制管理后台按钮的显示
|
||||||
updatedAt: null
|
updatedAt: null
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
siteName: 'Claude Relay Service',
|
siteName: 'Claude Relay Service',
|
||||||
siteIcon: '',
|
siteIcon: '',
|
||||||
siteIconData: '',
|
siteIconData: '',
|
||||||
|
showAdminButton: true,
|
||||||
updatedAt: null
|
updatedAt: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
<!-- 分隔线 -->
|
<!-- 分隔线 -->
|
||||||
<div
|
<div
|
||||||
|
v-if="oemSettings.ldapEnabled || oemSettings.showAdminButton !== false"
|
||||||
class="h-8 w-px bg-gradient-to-b from-transparent via-gray-300 to-transparent opacity-50 dark:via-gray-600"
|
class="h-8 w-px bg-gradient-to-b from-transparent via-gray-300 to-transparent opacity-50 dark:via-gray-600"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
<!-- 管理后台按钮 -->
|
<!-- 管理后台按钮 -->
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="oemSettings.showAdminButton !== false"
|
||||||
class="admin-button-refined flex items-center gap-2 rounded-2xl px-4 py-2 transition-all duration-300 md:px-5 md:py-2.5"
|
class="admin-button-refined flex items-center gap-2 rounded-2xl px-4 py-2 transition-all duration-300 md:px-5 md:py-2.5"
|
||||||
to="/dashboard"
|
to="/dashboard"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -147,6 +147,41 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<!-- 管理后台按钮显示控制 -->
|
||||||
|
<tr class="table-row">
|
||||||
|
<td class="w-48 whitespace-nowrap px-6 py-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div
|
||||||
|
class="mr-3 flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600"
|
||||||
|
>
|
||||||
|
<i class="fas fa-eye-slash text-xs text-white" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
||||||
|
管理入口
|
||||||
|
</div>
|
||||||
|
<div class="text-xs text-gray-500 dark:text-gray-400">登录按钮显示</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<label class="inline-flex cursor-pointer items-center">
|
||||||
|
<input v-model="hideAdminButton" class="peer sr-only" type="checkbox" />
|
||||||
|
<div
|
||||||
|
class="peer relative h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-blue-600 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:border-gray-600 dark:bg-gray-700 dark:peer-focus:ring-blue-800"
|
||||||
|
></div>
|
||||||
|
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">{{
|
||||||
|
hideAdminButton ? '隐藏登录按钮' : '显示登录按钮'
|
||||||
|
}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
隐藏后,用户需要直接访问 /admin/login 页面登录
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-6 py-6" colspan="2">
|
<td class="px-6 py-6" colspan="2">
|
||||||
@@ -189,7 +224,148 @@
|
|||||||
|
|
||||||
<!-- 移动端卡片视图 -->
|
<!-- 移动端卡片视图 -->
|
||||||
<div class="space-y-4 sm:hidden">
|
<div class="space-y-4 sm:hidden">
|
||||||
<!-- 省略移动端视图代码... -->
|
<!-- 站点名称卡片 -->
|
||||||
|
<div class="glass-card p-4">
|
||||||
|
<div class="mb-3 flex items-center gap-3">
|
||||||
|
<div
|
||||||
|
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-blue-500 to-cyan-600 text-white shadow-md"
|
||||||
|
>
|
||||||
|
<i class="fas fa-tag"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100">站点名称</h3>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-400">自定义您的站点品牌名称</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
v-model="oemSettings.siteName"
|
||||||
|
class="form-input w-full dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||||
|
maxlength="100"
|
||||||
|
placeholder="Claude Relay Service"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 站点图标卡片 -->
|
||||||
|
<div class="glass-card p-4">
|
||||||
|
<div class="mb-3 flex items-center gap-3">
|
||||||
|
<div
|
||||||
|
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-purple-500 to-pink-600 text-white shadow-md"
|
||||||
|
>
|
||||||
|
<i class="fas fa-image"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100">站点图标</h3>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
上传自定义图标或输入图标URL
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<!-- 图标预览 -->
|
||||||
|
<div
|
||||||
|
v-if="oemSettings.siteIconData || oemSettings.siteIcon"
|
||||||
|
class="inline-flex items-center gap-3 rounded-lg bg-gray-50 p-3 dark:bg-gray-700"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="图标预览"
|
||||||
|
class="h-8 w-8"
|
||||||
|
:src="oemSettings.siteIconData || oemSettings.siteIcon"
|
||||||
|
@error="handleIconError"
|
||||||
|
/>
|
||||||
|
<span class="text-sm text-gray-600 dark:text-gray-400">当前图标</span>
|
||||||
|
<button
|
||||||
|
class="rounded-lg px-3 py-1 font-medium text-red-600 transition-colors hover:bg-red-50 hover:text-red-900"
|
||||||
|
@click="removeIcon"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传按钮 -->
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
ref="iconFileInputMobile"
|
||||||
|
accept=".ico,.png,.jpg,.jpeg,.svg"
|
||||||
|
class="hidden"
|
||||||
|
type="file"
|
||||||
|
@change="handleIconUpload"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn btn-success px-4 py-2"
|
||||||
|
@click="$refs.iconFileInputMobile.click()"
|
||||||
|
>
|
||||||
|
<i class="fas fa-upload mr-2" />
|
||||||
|
上传图标
|
||||||
|
</button>
|
||||||
|
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
支持 .ico, .png, .jpg, .svg 格式,最大 350KB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 管理后台按钮显示控制卡片 -->
|
||||||
|
<div class="glass-card p-4">
|
||||||
|
<div class="mb-3 flex items-center gap-3">
|
||||||
|
<div
|
||||||
|
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-md"
|
||||||
|
>
|
||||||
|
<i class="fas fa-eye-slash"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100">管理入口</h3>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-400">控制登录按钮在首页的显示</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label class="inline-flex cursor-pointer items-center">
|
||||||
|
<input v-model="hideAdminButton" class="peer sr-only" type="checkbox" />
|
||||||
|
<div
|
||||||
|
class="peer relative h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-blue-600 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:border-gray-600 dark:bg-gray-700 dark:peer-focus:ring-blue-800"
|
||||||
|
></div>
|
||||||
|
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">{{
|
||||||
|
hideAdminButton ? '隐藏登录按钮' : '显示登录按钮'
|
||||||
|
}}</span>
|
||||||
|
</label>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
隐藏后,用户需要直接访问 /admin/login 页面登录
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮卡片 -->
|
||||||
|
<div class="glass-card p-4">
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary w-full px-6 py-3"
|
||||||
|
:class="{ 'cursor-not-allowed opacity-50': saving }"
|
||||||
|
:disabled="saving"
|
||||||
|
@click="saveOemSettings"
|
||||||
|
>
|
||||||
|
<div v-if="saving" class="loading-spinner mr-2"></div>
|
||||||
|
<i v-else class="fas fa-save mr-2" />
|
||||||
|
{{ saving ? '保存中...' : '保存设置' }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn w-full bg-gray-100 px-6 py-3 text-gray-700 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600"
|
||||||
|
:disabled="saving"
|
||||||
|
@click="resetOemSettings"
|
||||||
|
>
|
||||||
|
<i class="fas fa-undo mr-2" />
|
||||||
|
重置为默认
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="oemSettings.updatedAt"
|
||||||
|
class="text-center text-sm text-gray-500 dark:text-gray-400"
|
||||||
|
>
|
||||||
|
<i class="fas fa-clock mr-1" />
|
||||||
|
上次更新: {{ formatDateTime(oemSettings.updatedAt) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -791,6 +967,16 @@ const isMounted = ref(true)
|
|||||||
// API请求取消控制器
|
// API请求取消控制器
|
||||||
const abortController = ref(new AbortController())
|
const abortController = ref(new AbortController())
|
||||||
|
|
||||||
|
// 计算属性:隐藏管理后台按钮(反转 showAdminButton 的值)
|
||||||
|
const hideAdminButton = computed({
|
||||||
|
get() {
|
||||||
|
return !oemSettings.value.showAdminButton
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
oemSettings.value.showAdminButton = !value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// URL 验证状态
|
// URL 验证状态
|
||||||
const urlError = ref(false)
|
const urlError = ref(false)
|
||||||
const urlValid = ref(false)
|
const urlValid = ref(false)
|
||||||
@@ -1286,7 +1472,8 @@ const saveOemSettings = async () => {
|
|||||||
const settings = {
|
const settings = {
|
||||||
siteName: oemSettings.value.siteName,
|
siteName: oemSettings.value.siteName,
|
||||||
siteIcon: oemSettings.value.siteIcon,
|
siteIcon: oemSettings.value.siteIcon,
|
||||||
siteIconData: oemSettings.value.siteIconData
|
siteIconData: oemSettings.value.siteIconData,
|
||||||
|
showAdminButton: oemSettings.value.showAdminButton
|
||||||
}
|
}
|
||||||
const result = await settingsStore.saveOemSettings(settings)
|
const result = await settingsStore.saveOemSettings(settings)
|
||||||
if (result && result.success) {
|
if (result && result.success) {
|
||||||
|
|||||||
Reference in New Issue
Block a user