新功能: 1. 部门管理功能 - 管理员可在系统设置中添加/删除部门 - 用户注册时从下拉框选择部门 - 新增Department数据库表和API 2. 文件上传优化 - 支持直接上传源文件(.max/.psd/.ai/.cad/.dwg/.c4d) - 自动识别文件类型并设置素材类型 - 压缩包需手动选择类型 - 优化拖拽上传体验 数据库变更: - 新增departments表 - User表新增department字段
556 lines
23 KiB
TypeScript
556 lines
23 KiB
TypeScript
'use client'
|
||
|
||
import { useEffect, useState } from 'react'
|
||
import { useSession } from 'next-auth/react'
|
||
import { useRouter } from 'next/navigation'
|
||
import Header from '@/components/Header'
|
||
|
||
export default function SystemSettings() {
|
||
const { data: session, status } = useSession()
|
||
const router = useRouter()
|
||
const [loading, setLoading] = useState(true)
|
||
const [saving, setSaving] = useState(false)
|
||
const [uploading, setUploading] = useState(false)
|
||
|
||
// 设置状态
|
||
const [headerBgColor, setHeaderBgColor] = useState('#1f2937')
|
||
const [siteName, setSiteName] = useState('由壹点3D素材')
|
||
const [logoUrl, setLogoUrl] = useState('')
|
||
const [logoPreview, setLogoPreview] = useState('')
|
||
|
||
// 部门管理状态
|
||
const [departments, setDepartments] = useState<Array<{ id: string; name: string }>>([])
|
||
const [newDepartmentName, setNewDepartmentName] = useState('')
|
||
const [addingDepartment, setAddingDepartment] = useState(false)
|
||
|
||
// 权限检查
|
||
useEffect(() => {
|
||
if (status === 'unauthenticated') {
|
||
router.push('/login')
|
||
} else if (status === 'authenticated' && session?.user?.role !== 'ADMIN') {
|
||
router.push('/')
|
||
}
|
||
}, [status, session, router])
|
||
|
||
// 加载设置
|
||
useEffect(() => {
|
||
if (status === 'authenticated' && session?.user?.role === 'ADMIN') {
|
||
fetchSettings()
|
||
fetchDepartments()
|
||
}
|
||
}, [status, session])
|
||
|
||
const fetchSettings = async () => {
|
||
try {
|
||
const response = await fetch('/api/system-settings')
|
||
if (response.ok) {
|
||
const data = await response.json()
|
||
setHeaderBgColor(data.headerBgColor || '#1f2937')
|
||
setSiteName(data.siteName || '由壹点3D素材')
|
||
setLogoUrl(data.logoUrl || '')
|
||
setLogoPreview(data.logoUrl || '')
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching settings:', error)
|
||
alert('加载设置失败')
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
const fetchDepartments = async () => {
|
||
try {
|
||
const response = await fetch('/api/departments')
|
||
if (response.ok) {
|
||
const data = await response.json()
|
||
setDepartments(data)
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching departments:', error)
|
||
}
|
||
}
|
||
|
||
const handleAddDepartment = async () => {
|
||
if (!newDepartmentName.trim()) {
|
||
alert('请输入部门名称')
|
||
return
|
||
}
|
||
|
||
setAddingDepartment(true)
|
||
try {
|
||
const response = await fetch('/api/departments', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ name: newDepartmentName.trim() }),
|
||
})
|
||
|
||
if (response.ok) {
|
||
await fetchDepartments()
|
||
setNewDepartmentName('')
|
||
alert('部门添加成功')
|
||
} else {
|
||
const error = await response.json()
|
||
alert(error.error || '添加失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('Add department error:', error)
|
||
alert('添加失败,请稍后重试')
|
||
} finally {
|
||
setAddingDepartment(false)
|
||
}
|
||
}
|
||
|
||
const handleDeleteDepartment = async (id: string, name: string) => {
|
||
if (!confirm(`确定要删除部门"${name}"吗?`)) {
|
||
return
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/api/departments?id=${id}`, {
|
||
method: 'DELETE',
|
||
})
|
||
|
||
if (response.ok) {
|
||
await fetchDepartments()
|
||
alert('部门删除成功')
|
||
} else {
|
||
const error = await response.json()
|
||
alert(error.error || '删除失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('Delete department error:', error)
|
||
alert('删除失败,请稍后重试')
|
||
}
|
||
}
|
||
|
||
const handleSave = async () => {
|
||
setSaving(true)
|
||
try {
|
||
const response = await fetch('/api/system-settings', {
|
||
method: 'PUT',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
headerBgColor,
|
||
siteName,
|
||
}),
|
||
})
|
||
|
||
if (response.ok) {
|
||
alert('保存成功!页面将自动刷新以应用新设置')
|
||
// 刷新页面以应用新设置
|
||
window.location.reload()
|
||
} else {
|
||
const error = await response.json()
|
||
alert(error.error || '保存失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('Save settings error:', error)
|
||
alert('保存失败,请稍后重试')
|
||
} finally {
|
||
setSaving(false)
|
||
}
|
||
}
|
||
|
||
const handleLogoUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
const file = e.target.files?.[0]
|
||
if (!file) return
|
||
|
||
// 验证文件类型
|
||
if (!file.type.startsWith('image/')) {
|
||
alert('请选择图片文件')
|
||
return
|
||
}
|
||
|
||
// 验证文件大小(最大5MB)
|
||
if (file.size > 5 * 1024 * 1024) {
|
||
alert('LOGO文件大小不能超过5MB')
|
||
return
|
||
}
|
||
|
||
setUploading(true)
|
||
try {
|
||
const formData = new FormData()
|
||
formData.append('logo', file)
|
||
|
||
const response = await fetch('/api/system-settings/upload-logo', {
|
||
method: 'POST',
|
||
body: formData,
|
||
})
|
||
|
||
if (response.ok) {
|
||
const data = await response.json()
|
||
setLogoUrl(data.logoUrl)
|
||
setLogoPreview(data.logoUrl)
|
||
alert('LOGO上传成功!请点击"保存设置"以应用更改')
|
||
} else {
|
||
const error = await response.json()
|
||
alert(error.error || 'LOGO上传失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('Upload logo error:', error)
|
||
alert('上传失败,请稍后重试')
|
||
} finally {
|
||
setUploading(false)
|
||
}
|
||
}
|
||
|
||
const handleColorReset = () => {
|
||
setHeaderBgColor('#1f2937')
|
||
}
|
||
|
||
const handleLogoReset = () => {
|
||
setLogoPreview('http://s3.1080p.hk/shuzhou/2025/05/18/8ebadf0a7cc34eaea00e8619b8efb827.png')
|
||
}
|
||
|
||
if (status === 'loading' || loading) {
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center dark:bg-gray-900">
|
||
<div className="text-xl text-gray-600 dark:text-gray-400">加载中...</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
if (!session || session.user.role !== 'ADMIN') {
|
||
return null
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||
<Header session={session} />
|
||
|
||
<main className="container mx-auto px-4 py-8 max-w-4xl">
|
||
<div className="mb-6">
|
||
<h1 className="text-3xl font-bold text-gray-900 dark:text-white mb-2">系统设置</h1>
|
||
<p className="text-gray-600 dark:text-gray-400">自定义网站外观和品牌信息</p>
|
||
</div>
|
||
|
||
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 space-y-8">
|
||
{/* 网站名称设置 */}
|
||
<div>
|
||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
|
||
<svg className="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
||
</svg>
|
||
网站名称
|
||
</h2>
|
||
<div className="space-y-2">
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||
站点名称
|
||
</label>
|
||
<input
|
||
type="text"
|
||
value={siteName}
|
||
onChange={(e) => setSiteName(e.target.value)}
|
||
placeholder="由壹点3D素材"
|
||
className="w-full px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white focus:border-blue-500 dark:focus:border-blue-400 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-600 outline-none transition-all"
|
||
/>
|
||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||
该名称将显示在顶部导航栏和登录页面
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* LOGO设置 */}
|
||
<div className="border-t border-gray-200 dark:border-gray-700 pt-8">
|
||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
|
||
<svg className="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||
</svg>
|
||
网站LOGO
|
||
</h2>
|
||
<div className="space-y-4">
|
||
{/* LOGO预览 */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||
当前LOGO预览
|
||
</label>
|
||
<div className="flex items-center gap-4">
|
||
<div className="w-32 h-32 rounded-lg border-2 border-gray-300 dark:border-gray-600 flex items-center justify-center overflow-hidden bg-gray-50 dark:bg-gray-700">
|
||
{logoPreview ? (
|
||
<img src={logoPreview} alt="LOGO" className="max-w-full max-h-full object-contain" />
|
||
) : (
|
||
<svg className="w-16 h-16 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||
</svg>
|
||
)}
|
||
</div>
|
||
<div className="flex-1">
|
||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-2">
|
||
建议尺寸:200x200px,支持PNG、JPG、SVG格式
|
||
</p>
|
||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||
文件大小不超过5MB
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 上传按钮 */}
|
||
<div className="flex gap-3">
|
||
<label className="btn-primary cursor-pointer inline-flex items-center gap-2 disabled:opacity-50">
|
||
{uploading ? (
|
||
<>
|
||
<svg className="w-5 h-5 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||
</svg>
|
||
上传中...
|
||
</>
|
||
) : (
|
||
<>
|
||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
|
||
</svg>
|
||
上传LOGO
|
||
</>
|
||
)}
|
||
<input
|
||
type="file"
|
||
accept="image/*"
|
||
onChange={handleLogoUpload}
|
||
disabled={uploading}
|
||
className="hidden"
|
||
/>
|
||
</label>
|
||
<button
|
||
onClick={handleLogoReset}
|
||
className="btn-secondary"
|
||
disabled={uploading}
|
||
>
|
||
恢复默认
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 顶部导航栏颜色设置 */}
|
||
<div className="border-t border-gray-200 dark:border-gray-700 pt-8">
|
||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
|
||
<svg className="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
|
||
</svg>
|
||
顶部导航栏颜色
|
||
</h2>
|
||
<div className="space-y-4">
|
||
{/* 颜色预览 */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||
颜色预览
|
||
</label>
|
||
<div
|
||
className="w-full h-16 rounded-lg border-2 border-gray-300 dark:border-gray-600 shadow-inner"
|
||
style={{ backgroundColor: headerBgColor }}
|
||
>
|
||
<div className="flex items-center h-full px-4">
|
||
<span className="text-white font-medium" style={{ textShadow: '0 1px 2px rgba(0,0,0,0.3)' }}>
|
||
顶部导航栏预览
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 颜色选择器 */}
|
||
<div className="flex items-center gap-4">
|
||
<div className="flex-1">
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||
选择颜色
|
||
</label>
|
||
<div className="flex items-center gap-2">
|
||
<input
|
||
type="color"
|
||
value={headerBgColor}
|
||
onChange={(e) => setHeaderBgColor(e.target.value)}
|
||
className="w-16 h-12 rounded cursor-pointer border border-gray-300 dark:border-gray-600"
|
||
/>
|
||
<input
|
||
type="text"
|
||
value={headerBgColor}
|
||
onChange={(e) => setHeaderBgColor(e.target.value)}
|
||
placeholder="#1f2937"
|
||
className="flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white focus:border-blue-500 dark:focus:border-blue-400 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-600 outline-none transition-all font-mono"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 opacity-0">
|
||
操作
|
||
</label>
|
||
<button
|
||
onClick={handleColorReset}
|
||
className="btn-secondary whitespace-nowrap"
|
||
>
|
||
恢复默认
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 预设颜色 */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||
快速选择
|
||
</label>
|
||
<div className="flex flex-wrap gap-2">
|
||
{[
|
||
{ name: '默认灰', color: '#1f2937' },
|
||
{ name: '深蓝', color: '#1e3a8a' },
|
||
{ name: '靛蓝', color: '#4f46e5' },
|
||
{ name: '紫色', color: '#7c3aed' },
|
||
{ name: '粉色', color: '#db2777' },
|
||
{ name: '红色', color: '#dc2626' },
|
||
{ name: '橙色', color: '#ea580c' },
|
||
{ name: '绿色', color: '#059669' },
|
||
{ name: '青色', color: '#0891b2' },
|
||
{ name: '深灰', color: '#374151' },
|
||
].map((preset) => (
|
||
<button
|
||
key={preset.color}
|
||
onClick={() => setHeaderBgColor(preset.color)}
|
||
className={`px-4 py-2 rounded-lg border-2 transition-all ${
|
||
headerBgColor === preset.color
|
||
? 'border-blue-500 ring-2 ring-blue-200'
|
||
: 'border-gray-300 dark:border-gray-600 hover:border-gray-400'
|
||
}`}
|
||
style={{ backgroundColor: preset.color }}
|
||
title={preset.color}
|
||
>
|
||
<span className="text-white text-sm font-medium" style={{ textShadow: '0 1px 2px rgba(0,0,0,0.5)' }}>
|
||
{preset.name}
|
||
</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 部门管理 */}
|
||
<div className="border-t border-gray-200 dark:border-gray-700 pt-8">
|
||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
|
||
<svg className="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||
</svg>
|
||
部门管理
|
||
</h2>
|
||
<div className="space-y-4">
|
||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||
管理系统中的部门列表,用户注册时可以选择所属部门
|
||
</p>
|
||
|
||
{/* 添加部门 */}
|
||
<div className="flex gap-2">
|
||
<input
|
||
type="text"
|
||
value={newDepartmentName}
|
||
onChange={(e) => setNewDepartmentName(e.target.value)}
|
||
onKeyPress={(e) => {
|
||
if (e.key === 'Enter') {
|
||
handleAddDepartment()
|
||
}
|
||
}}
|
||
placeholder="输入部门名称(例如:设计部、技术部等)"
|
||
className="flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white focus:border-blue-500 dark:focus:border-blue-400 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-600 outline-none transition-all"
|
||
disabled={addingDepartment}
|
||
/>
|
||
<button
|
||
onClick={handleAddDepartment}
|
||
disabled={addingDepartment}
|
||
className="btn-primary whitespace-nowrap disabled:opacity-50"
|
||
>
|
||
{addingDepartment ? '添加中...' : '添加部门'}
|
||
</button>
|
||
</div>
|
||
|
||
{/* 部门列表 */}
|
||
<div className="mt-4">
|
||
{departments.length === 0 ? (
|
||
<div className="text-center py-8 text-gray-500 dark:text-gray-400">
|
||
暂无部门,请添加第一个部门
|
||
</div>
|
||
) : (
|
||
<div className="space-y-2">
|
||
{departments.map((dept) => (
|
||
<div
|
||
key={dept.id}
|
||
className="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded-lg border border-gray-200 dark:border-gray-600"
|
||
>
|
||
<span className="text-gray-900 dark:text-white font-medium">
|
||
{dept.name}
|
||
</span>
|
||
<button
|
||
onClick={() => handleDeleteDepartment(dept.id, dept.name)}
|
||
className="text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
||
title="删除部门"
|
||
>
|
||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 保存按钮 */}
|
||
<div className="border-t border-gray-200 dark:border-gray-700 pt-6 flex justify-between items-center">
|
||
<button
|
||
onClick={() => router.push('/admin')}
|
||
className="btn-secondary"
|
||
>
|
||
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||
</svg>
|
||
返回
|
||
</button>
|
||
<button
|
||
onClick={handleSave}
|
||
disabled={saving}
|
||
className="btn-primary text-lg px-8 py-3 disabled:opacity-50"
|
||
>
|
||
{saving ? (
|
||
<>
|
||
<svg className="w-5 h-5 mr-2 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||
</svg>
|
||
保存中...
|
||
</>
|
||
) : (
|
||
<>
|
||
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||
</svg>
|
||
保存设置
|
||
</>
|
||
)}
|
||
</button>
|
||
</div>
|
||
|
||
{/* 提示信息 */}
|
||
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
|
||
<div className="flex items-start gap-3">
|
||
<svg className="w-5 h-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||
</svg>
|
||
<div className="text-sm text-blue-800 dark:text-blue-300">
|
||
<p className="font-medium mb-1">温馨提示:</p>
|
||
<ul className="list-disc list-inside space-y-1">
|
||
<li>修改设置后点击“保存设置”按钮,页面会自动刷新以应用新的设置</li>
|
||
<li>LOGO会自动上传到MinIO S3存储桶,确保全站可访问</li>
|
||
<li>建议使用高质量的LOGO图片以获得最佳显示效果</li>
|
||
<li>顶部导航栏颜色建议选择深色系,以确保白色文字清晰可见</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
)
|
||
}
|
||
|