前端样式第一版已完成

This commit is contained in:
2025-07-29 12:43:09 +08:00
commit 4b2d0a6e94
62 changed files with 10693 additions and 0 deletions

View File

@@ -0,0 +1,427 @@
<template>
<div class="space-y-6">
<!-- 页面标题 -->
<div>
<h1 class="text-2xl font-bold text-gray-900">系统设置</h1>
<p class="text-gray-600 mt-1">配置系统参数和功能选项</p>
</div>
<!-- 设置选项卡 -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200">
<nav class="flex border-b border-gray-200">
<button
v-for="tab in tabs"
:key="tab.key"
@click="activeTab = tab.key"
:class="[
'px-6 py-4 text-sm font-medium border-b-2 transition-colors',
activeTab === tab.key
? 'border-blue-500 text-blue-600'
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
]"
>
{{ tab.name }}
</button>
</nav>
<div class="p-6">
<!-- 基础设置 -->
<div v-if="activeTab === 'basic'" class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">网站名称</label>
<input
v-model="settings.siteName"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">网站标语</label>
<input
v-model="settings.siteSlogan"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div class="md:col-span-2">
<label class="block text-sm font-medium text-gray-700 mb-2">网站描述</label>
<textarea
v-model="settings.siteDescription"
rows="3"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">联系邮箱</label>
<input
v-model="settings.contactEmail"
type="email"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">备案号</label>
<input
v-model="settings.icp"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
</div>
<!-- 安全设置 -->
<div v-if="activeTab === 'security'" class="space-y-6">
<div class="space-y-4">
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div>
<h4 class="text-sm font-medium text-gray-900">启用两步验证</h4>
<p class="text-sm text-gray-500">为管理员账户启用两步验证以提高安全性</p>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input
v-model="settings.twoFactorAuth"
type="checkbox"
class="sr-only peer"
/>
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
</label>
</div>
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div>
<h4 class="text-sm font-medium text-gray-900">登录验证码</h4>
<p class="text-sm text-gray-500">登录时需要输入图形验证码</p>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input
v-model="settings.loginCaptcha"
type="checkbox"
class="sr-only peer"
/>
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">密码最小长度</label>
<select
v-model="settings.minPasswordLength"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="6">6</option>
<option value="8">8</option>
<option value="10">10</option>
<option value="12">12</option>
</select>
</div>
</div>
</div>
<!-- 邮件设置 -->
<div v-if="activeTab === 'email'" class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">SMTP服务器</label>
<input
v-model="settings.smtpHost"
type="text"
placeholder="smtp.example.com"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">SMTP端口</label>
<input
v-model="settings.smtpPort"
type="number"
placeholder="587"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">发件人邮箱</label>
<input
v-model="settings.fromEmail"
type="email"
placeholder="noreply@example.com"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">发件人名称</label>
<input
v-model="settings.fromName"
type="text"
placeholder="系统管理员"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">用户名</label>
<input
v-model="settings.smtpUsername"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">密码</label>
<input
v-model="settings.smtpPassword"
type="password"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
</div>
<!-- 存储设置 -->
<div v-if="activeTab === 'storage'" class="space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">存储类型</label>
<select
v-model="settings.storageType"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="local">本地存储</option>
<option value="oss">阿里云OSS</option>
<option value="cos">腾讯云COS</option>
<option value="qiniu">七牛云</option>
</select>
</div>
<div v-if="settings.storageType !== 'local'" class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Access Key</label>
<input
v-model="settings.accessKey"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Secret Key</label>
<input
v-model="settings.secretKey"
type="password"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">存储桶名称</label>
<input
v-model="settings.bucket"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">访问域名</label>
<input
v-model="settings.domain"
type="text"
placeholder="https://example.com"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">最大文件大小MB</label>
<input
v-model="settings.maxFileSize"
type="number"
min="1"
max="100"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">允许的文件类型</label>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-2">
<label v-for="type in fileTypes" :key="type.value" class="flex items-center">
<input
v-model="settings.allowedFileTypes"
:value="type.value"
type="checkbox"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<span class="ml-2 text-sm text-gray-700">{{ type.label }}</span>
</label>
</div>
</div>
</div>
</div>
<!-- 系统信息 -->
<div v-if="activeTab === 'system'" class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-900 mb-2">系统版本</h4>
<p class="text-lg font-semibold text-blue-600">v1.0.0</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-900 mb-2">数据库大小</h4>
<p class="text-lg font-semibold text-purple-600">45.2 MB</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-900 mb-2">存储空间</h4>
<p class="text-lg font-semibold text-green-600">2.1 GB</p>
</div>
</div>
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
<div class="flex">
<div class="flex-shrink-0">
<WarningIcon class="h-5 w-5 text-yellow-400" />
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">系统维护建议</h3>
<div class="mt-2 text-sm text-yellow-700">
<p>建议定期清理系统缓存和日志文件以保持系统性能</p>
</div>
<div class="mt-4 flex space-x-3">
<button
@click="clearCache"
class="bg-yellow-100 hover:bg-yellow-200 text-yellow-800 px-3 py-1 rounded text-sm"
>
清理缓存
</button>
<button
@click="clearLogs"
class="bg-yellow-100 hover:bg-yellow-200 text-yellow-800 px-3 py-1 rounded text-sm"
>
清理日志
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 保存按钮 -->
<div class="flex justify-end pt-6 border-t border-gray-200">
<button
@click="saveSettings"
class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg"
>
保存设置
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 图标组件
const WarningIcon = {
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg>`
}
// 响应式数据
const activeTab = ref('basic')
const tabs = [
{ key: 'basic', name: '基础设置' },
{ key: 'security', name: '安全设置' },
{ key: 'email', name: '邮件设置' },
{ key: 'storage', name: '存储设置' },
{ key: 'system', name: '系统信息' }
]
const settings = ref({
// 基础设置
siteName: 'CMS管理系统',
siteSlogan: '高效、安全、易用的内容管理系统',
siteDescription: '这是一个基于Vue3和TailwindCSS构建的现代化内容管理系统提供完整的文章管理、用户管理和系统配置功能。',
contactEmail: 'admin@example.com',
icp: '京ICP备12345678号',
// 安全设置
twoFactorAuth: false,
loginCaptcha: true,
minPasswordLength: '8',
// 邮件设置
smtpHost: '',
smtpPort: 587,
fromEmail: 'noreply@example.com',
fromName: '系统管理员',
smtpUsername: '',
smtpPassword: '',
// 存储设置
storageType: 'local',
accessKey: '',
secretKey: '',
bucket: '',
domain: '',
maxFileSize: 10,
allowedFileTypes: ['jpg', 'png', 'gif', 'pdf', 'doc']
})
const fileTypes = [
{ value: 'jpg', label: 'JPG图片' },
{ value: 'png', label: 'PNG图片' },
{ value: 'gif', label: 'GIF图片' },
{ value: 'pdf', label: 'PDF文档' },
{ value: 'doc', label: 'Word文档' },
{ value: 'xls', label: 'Excel表格' },
{ value: 'zip', label: 'ZIP压缩包' },
{ value: 'mp4', label: 'MP4视频' }
]
// 保存设置
const saveSettings = () => {
console.log('保存设置:', settings.value)
// 这里应该调用API保存设置
alert('设置保存成功!')
}
// 清理缓存
const clearCache = () => {
if (confirm('确定要清理系统缓存吗?')) {
console.log('清理缓存')
// 这里应该调用API清理缓存
alert('缓存清理完成!')
}
}
// 清理日志
const clearLogs = () => {
if (confirm('确定要清理系统日志吗?此操作不可恢复!')) {
console.log('清理日志')
// 这里应该调用API清理日志
alert('日志清理完成!')
}
}
</script>
<style scoped>
/* 开关样式 */
.peer:checked ~ .peer-checked\:bg-blue-600 {
background-color: #2563eb;
}
/* 响应式优化 */
@media (max-width: 1024px) {
.grid-cols-1.md\:grid-cols-2 {
grid-template-columns: 1fr;
}
.grid-cols-1.md\:grid-cols-3 {
grid-template-columns: 1fr;
}
}
/* 标签页导航样式 */
nav ul li button {
transition: all 0.2s ease-in-out;
}
</style>