1078 lines
30 KiB
Plaintext
1078 lines
30 KiB
Plaintext
<template>
|
||
<AdminLayout current-page="system">
|
||
<view class="system-settings">
|
||
<!-- 页面标题 -->
|
||
<view class="page-header">
|
||
<text class="page-title">系统设置</text>
|
||
<text class="page-subtitle">管理系统基础配置和参数</text>
|
||
</view>
|
||
|
||
<!-- Tab 切换栏 -->
|
||
<view class="tab-bar">
|
||
<view
|
||
v-for="tab in tabs"
|
||
:key="tab.key"
|
||
class="tab-item"
|
||
:class="{ 'active': activeTab === tab.key }"
|
||
@click="switchTab(tab.key)"
|
||
>
|
||
<text class="iconfont tab-icon">{{ tab.icon }}</text>
|
||
<text class="tab-title">{{ tab.title }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 设置分类导航 -->
|
||
<view class="settings-nav">
|
||
<view
|
||
v-for="category in settingCategories"
|
||
:key="category.id"
|
||
class="nav-item"
|
||
:class="{ 'active': activeCategory === category.id }"
|
||
@click="setActiveCategory(category.id)"
|
||
>
|
||
<text class="nav-icon">{{ category.icon }}</text>
|
||
<text class="nav-text">{{ category.name }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 设置内容区域 -->
|
||
<view class="settings-content">
|
||
<!-- 基本设置 -->
|
||
<view v-if="activeCategory === 'basic'" class="setting-section">
|
||
<view class="section-header">
|
||
<text class="section-title">基本设置</text>
|
||
<text class="section-desc">网站基本信息和显示设置</text>
|
||
</view>
|
||
|
||
<view class="setting-items">
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">网站名称</text>
|
||
<text class="item-desc">显示在网站标题和页面的网站名称</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.siteName"
|
||
class="setting-input"
|
||
placeholder="请输入网站名称"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">网站描述</text>
|
||
<text class="item-desc">网站简介,用于SEO优化</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<textarea
|
||
v-model="settings.siteDescription"
|
||
class="setting-textarea"
|
||
placeholder="请输入网站描述"
|
||
:maxlength="200"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">网站Logo</text>
|
||
<text class="item-desc">网站Logo图片,建议尺寸200x60px</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="image-upload">
|
||
<view class="upload-area" @click="handleLogoUpload">
|
||
<text class="iconfont icon-upload"></text>
|
||
<text class="upload-text">点击上传Logo</text>
|
||
</view>
|
||
<view v-if="settings.siteLogo" class="image-preview">
|
||
<image :src="settings.siteLogo" class="preview-image" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">网站状态</text>
|
||
<text class="item-desc">控制网站是否开放访问</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.siteStatus"
|
||
@change="handleSiteStatusChange"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.siteStatus ? '开放' : '维护中' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">维护提示信息</text>
|
||
<text class="item-desc">网站维护时显示的提示信息</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<textarea
|
||
v-model="settings.maintenanceMessage"
|
||
class="setting-textarea"
|
||
placeholder="请输入维护提示信息"
|
||
:disabled="!settings.siteStatus"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 安全设置 -->
|
||
<view v-else-if="activeCategory === 'security'" class="setting-section">
|
||
<view class="section-header">
|
||
<text class="section-title">安全设置</text>
|
||
<text class="section-desc">账号安全和登录相关配置</text>
|
||
</view>
|
||
|
||
<view class="setting-items">
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">登录失败锁定</text>
|
||
<text class="item-desc">连续登录失败后锁定账号</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.loginLockEnabled"
|
||
@change="settings.loginLockEnabled = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.loginLockEnabled ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">允许失败次数</text>
|
||
<text class="item-desc">连续登录失败的最大次数</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.maxLoginAttempts"
|
||
class="setting-input small"
|
||
type="number"
|
||
:disabled="!settings.loginLockEnabled"
|
||
min="3"
|
||
max="10"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">锁定时间(分钟)</text>
|
||
<text class="item-desc">账号锁定的持续时间</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.lockDuration"
|
||
class="setting-input small"
|
||
type="number"
|
||
:disabled="!settings.loginLockEnabled"
|
||
min="5"
|
||
max="1440"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">密码复杂度要求</text>
|
||
<text class="item-desc">用户密码必须包含的字符类型</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="checkbox-group">
|
||
<view class="checkbox-item">
|
||
<checkbox
|
||
:checked="settings.passwordRequireUppercase"
|
||
@change="settings.passwordRequireUppercase = $event.detail.value"
|
||
/>
|
||
<text>大写字母</text>
|
||
</view>
|
||
<view class="checkbox-item">
|
||
<checkbox
|
||
:checked="settings.passwordRequireLowercase"
|
||
@change="settings.passwordRequireLowercase = $event.detail.value"
|
||
/>
|
||
<text>小写字母</text>
|
||
</view>
|
||
<view class="checkbox-item">
|
||
<checkbox
|
||
:checked="settings.passwordRequireNumbers"
|
||
@change="settings.passwordRequireNumbers = $event.detail.value"
|
||
/>
|
||
<text>数字</text>
|
||
</view>
|
||
<view class="checkbox-item">
|
||
<checkbox
|
||
:checked="settings.passwordRequireSymbols"
|
||
@change="settings.passwordRequireSymbols = $event.detail.value"
|
||
/>
|
||
<text>特殊字符</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">密码最小长度</text>
|
||
<text class="item-desc">密码的最小字符长度</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.minPasswordLength"
|
||
class="setting-input small"
|
||
type="number"
|
||
min="6"
|
||
max="32"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">会话超时时间</text>
|
||
<text class="item-desc">用户登录后的会话有效期(分钟)</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.sessionTimeout"
|
||
class="setting-input small"
|
||
type="number"
|
||
min="15"
|
||
max="1440"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 邮件设置 -->
|
||
<view v-else-if="activeCategory === 'email'" class="setting-section">
|
||
<view class="section-header">
|
||
<text class="section-title">邮件设置</text>
|
||
<text class="section-desc">邮件服务器配置和模板设置</text>
|
||
</view>
|
||
|
||
<view class="setting-items">
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">SMTP服务器</text>
|
||
<text class="item-desc">邮件发送服务器地址</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.smtpHost"
|
||
class="setting-input"
|
||
placeholder="smtp.example.com"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">SMTP端口</text>
|
||
<text class="item-desc">邮件服务器端口号</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.smtpPort"
|
||
class="setting-input small"
|
||
type="number"
|
||
placeholder="587"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">发件人邮箱</text>
|
||
<text class="item-desc">系统邮件的发件人地址</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.smtpUsername"
|
||
class="setting-input"
|
||
placeholder="noreply@example.com"
|
||
type="email"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">授权密码</text>
|
||
<text class="item-desc">邮箱授权密码或应用密码</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.smtpPassword"
|
||
class="setting-input"
|
||
placeholder="请输入授权密码"
|
||
type="password"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">启用SSL</text>
|
||
<text class="item-desc">是否启用SSL加密连接</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.smtpSSL"
|
||
@change="settings.smtpSSL = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.smtpSSL ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">测试邮件</text>
|
||
<text class="item-desc">发送测试邮件验证配置是否正确</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<button class="btn-secondary" @click="sendTestEmail">
|
||
发送测试邮件
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 支付设置 -->
|
||
<view v-else-if="activeCategory === 'payment'" class="setting-section">
|
||
<view class="section-header">
|
||
<text class="section-title">支付设置</text>
|
||
<text class="section-desc">第三方支付平台配置</text>
|
||
</view>
|
||
|
||
<view class="setting-items">
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">支付宝支付</text>
|
||
<text class="item-desc">启用支付宝在线支付</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.alipayEnabled"
|
||
@change="settings.alipayEnabled = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.alipayEnabled ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">支付宝应用ID</text>
|
||
<text class="item-desc">支付宝开放平台的应用ID</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.alipayAppId"
|
||
class="setting-input"
|
||
placeholder="请输入应用ID"
|
||
:disabled="!settings.alipayEnabled"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">微信支付</text>
|
||
<text class="item-desc">启用微信支付</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.wechatPayEnabled"
|
||
@change="settings.wechatPayEnabled = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.wechatPayEnabled ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">微信商户号</text>
|
||
<text class="item-desc">微信支付商户号</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<input
|
||
v-model="settings.wechatMerchantId"
|
||
class="setting-input"
|
||
placeholder="请输入商户号"
|
||
:disabled="!settings.wechatPayEnabled"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">货币单位</text>
|
||
<text class="item-desc">系统使用的货币单位</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<picker
|
||
mode="selector"
|
||
:range="currencyOptions"
|
||
:value="settings.currency"
|
||
@change="settings.currency = $event.detail.value"
|
||
>
|
||
<view class="setting-select">
|
||
<text>{{ currencyOptions[settings.currency] }}</text>
|
||
<text class="iconfont icon-down"></text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 其他设置 -->
|
||
<view v-else-if="activeCategory === 'other'" class="setting-section">
|
||
<view class="section-header">
|
||
<text class="section-title">其他设置</text>
|
||
<text class="section-desc">其他系统配置选项</text>
|
||
</view>
|
||
|
||
<view class="setting-items">
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">数据备份</text>
|
||
<text class="item-desc">定期自动备份系统数据</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.autoBackupEnabled"
|
||
@change="settings.autoBackupEnabled = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.autoBackupEnabled ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">备份频率</text>
|
||
<text class="item-desc">自动备份的时间间隔</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<picker
|
||
mode="selector"
|
||
:range="backupFrequencyOptions"
|
||
:value="settings.backupFrequency"
|
||
@change="settings.backupFrequency = $event.detail.value"
|
||
:disabled="!settings.autoBackupEnabled"
|
||
>
|
||
<view class="setting-select">
|
||
<text>{{ backupFrequencyOptions[settings.backupFrequency] }}</text>
|
||
<text class="iconfont icon-down"></text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">系统日志</text>
|
||
<text class="item-desc">启用详细的系统操作日志</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.systemLoggingEnabled"
|
||
@change="settings.systemLoggingEnabled = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.systemLoggingEnabled ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="setting-item">
|
||
<view class="item-info">
|
||
<text class="item-title">API限流</text>
|
||
<text class="item-desc">限制API请求频率,防止滥用</text>
|
||
</view>
|
||
<view class="item-control">
|
||
<view class="switch-wrapper">
|
||
<switch
|
||
:checked="settings.apiRateLimitingEnabled"
|
||
@change="settings.apiRateLimitingEnabled = $event.detail.value"
|
||
color="#1890ff"
|
||
/>
|
||
<text class="switch-text">{{ settings.apiRateLimitingEnabled ? '启用' : '禁用' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 保存设置 -->
|
||
<view class="settings-footer">
|
||
<view class="action-buttons">
|
||
<button class="btn-secondary" @click="resetSettings">
|
||
重置设置
|
||
</button>
|
||
<button class="btn-primary" @click="saveSettings">
|
||
保存设置
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</AdminLayout>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { ref } from 'vue'
|
||
import AdminLayout from '@/layouts/admin/index.uvue'
|
||
|
||
// Tab 相关
|
||
const activeTab = ref('basic')
|
||
const tabs = ref([
|
||
{ key: 'basic', title: '基本设置', icon: 'icon-basic' },
|
||
{ key: 'security', title: '安全设置', icon: 'icon-security' },
|
||
{ key: 'email', title: '邮件设置', icon: 'icon-email' }
|
||
])
|
||
|
||
// 设置分类
|
||
const settingCategories = [
|
||
{ id: 'basic', name: '基本设置', icon: '🏠' },
|
||
{ id: 'security', name: '安全设置', icon: '🔒' },
|
||
{ id: 'email', name: '邮件设置', icon: '📧' },
|
||
{ id: 'payment', name: '支付设置', icon: '💳' },
|
||
{ id: 'other', name: '其他设置', icon: '⚙️' }
|
||
]
|
||
|
||
// 响应式数据
|
||
const activeCategory = ref('basic')
|
||
|
||
// 系统设置
|
||
const settings = ref({
|
||
// 基本设置
|
||
siteName: 'Mall电商平台',
|
||
siteDescription: '专业的多角色电商解决方案',
|
||
siteLogo: '',
|
||
siteStatus: true,
|
||
maintenanceMessage: '系统正在维护中,请稍后访问',
|
||
|
||
// 安全设置
|
||
loginLockEnabled: true,
|
||
maxLoginAttempts: 5,
|
||
lockDuration: 30,
|
||
passwordRequireUppercase: true,
|
||
passwordRequireLowercase: true,
|
||
passwordRequireNumbers: true,
|
||
passwordRequireSymbols: false,
|
||
minPasswordLength: 8,
|
||
sessionTimeout: 120,
|
||
|
||
// 邮件设置
|
||
smtpHost: 'smtp.qq.com',
|
||
smtpPort: 587,
|
||
smtpUsername: '',
|
||
smtpPassword: '',
|
||
smtpSSL: true,
|
||
|
||
// 支付设置
|
||
alipayEnabled: true,
|
||
alipayAppId: '',
|
||
wechatPayEnabled: true,
|
||
wechatMerchantId: '',
|
||
currency: 0,
|
||
|
||
// 其他设置
|
||
autoBackupEnabled: true,
|
||
backupFrequency: 0,
|
||
systemLoggingEnabled: true,
|
||
apiRateLimitingEnabled: true
|
||
})
|
||
|
||
// 选项数据
|
||
const currencyOptions = ['人民币(CNY)', '美元(USD)', '欧元(EUR)']
|
||
const backupFrequencyOptions = ['每日', '每周', '每月']
|
||
|
||
// 方法
|
||
const setActiveCategory = (categoryId: string) => {
|
||
activeCategory.value = categoryId
|
||
}
|
||
|
||
const handleSiteStatusChange = (e: any) => {
|
||
settings.value.siteStatus = e.detail.value
|
||
}
|
||
|
||
const handleLogoUpload = () => {
|
||
uni.showToast({
|
||
title: 'Logo上传功能开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
const sendTestEmail = () => {
|
||
if (!settings.value.smtpHost || !settings.value.smtpUsername) {
|
||
uni.showToast({
|
||
title: '请先配置邮件服务器信息',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '发送测试邮件...',
|
||
icon: 'loading',
|
||
duration: 2000
|
||
})
|
||
|
||
// TODO: 实现发送测试邮件逻辑
|
||
setTimeout(() => {
|
||
uni.showToast({
|
||
title: '测试邮件发送成功',
|
||
icon: 'success'
|
||
})
|
||
}, 2000)
|
||
}
|
||
|
||
const resetSettings = () => {
|
||
uni.showModal({
|
||
title: '确认重置',
|
||
content: '确定要重置所有设置为默认值吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// TODO: 实现重置设置逻辑
|
||
uni.showToast({
|
||
title: '设置已重置',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const saveSettings = () => {
|
||
// 表单验证
|
||
if (!settings.value.siteName.trim()) {
|
||
uni.showToast({
|
||
title: '请输入网站名称',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// TODO: 实现保存设置逻辑
|
||
console.log('保存设置:', settings.value)
|
||
|
||
uni.showToast({
|
||
title: '设置保存成功',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 生命周期
|
||
// Tab 切换方法
|
||
const switchTab = (tabKey: string) => {
|
||
activeTab.value = tabKey
|
||
}
|
||
|
||
// 页面生命周期
|
||
onLoad((options: any) => {
|
||
// 处理页面参数,切换到对应的tab
|
||
if (options && options.tab) {
|
||
if (['basic', 'security', 'email'].includes(options.tab)) {
|
||
activeTab.value = options.tab
|
||
} else {
|
||
activeTab.value = 'basic'
|
||
}
|
||
} else {
|
||
activeTab.value = 'basic'
|
||
}
|
||
|
||
console.log('系统设置页面加载,参数:', options)
|
||
})
|
||
|
||
onMounted(() => {
|
||
// 初始化设置数据
|
||
console.log('系统设置页面初始化')
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
/* Tab 栏样式 */
|
||
.tab-bar {
|
||
display: flex;
|
||
background-color: #ffffff;
|
||
border-radius: 8rpx;
|
||
padding: 8rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8rpx;
|
||
padding: 16rpx 24rpx;
|
||
border-radius: 6rpx;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
background-color: #f5f5f5;
|
||
color: #666666;
|
||
}
|
||
|
||
.tab-item:hover {
|
||
background-color: #e8e8e8;
|
||
}
|
||
|
||
.tab-item.active {
|
||
background-color: #1890ff;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.tab-icon {
|
||
font-size: 16rpx;
|
||
}
|
||
|
||
.tab-title {
|
||
font-size: 14rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.system-settings {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.page-header {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.page-title {
|
||
display: block;
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.page-subtitle {
|
||
display: block;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.settings-nav {
|
||
display: flex;
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 20rpx;
|
||
margin-bottom: 30rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.nav-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 20rpx 30rpx;
|
||
margin-right: 20rpx;
|
||
border-radius: 8rpx;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
min-width: 120rpx;
|
||
}
|
||
|
||
.nav-item:last-child {
|
||
margin-right: 0;
|
||
}
|
||
|
||
.nav-item.active {
|
||
background-color: #1890ff;
|
||
color: #fff;
|
||
}
|
||
|
||
.nav-item:not(.active):hover {
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.nav-icon {
|
||
font-size: 32rpx;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.nav-text {
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.settings-content {
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 30rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.setting-section {
|
||
min-height: 400rpx;
|
||
}
|
||
|
||
.section-header {
|
||
margin-bottom: 30rpx;
|
||
padding-bottom: 20rpx;
|
||
border-bottom: 1rpx solid #eee;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
}
|
||
|
||
.section-desc {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.setting-items {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 30rpx;
|
||
}
|
||
|
||
.setting-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
padding: 20rpx 0;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
}
|
||
|
||
.setting-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.item-info {
|
||
flex: 2;
|
||
margin-right: 30rpx;
|
||
}
|
||
|
||
.item-title {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 6rpx;
|
||
display: block;
|
||
}
|
||
|
||
.item-desc {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.item-control {
|
||
flex: 1;
|
||
min-width: 200rpx;
|
||
}
|
||
|
||
.setting-input {
|
||
width: 100%;
|
||
padding: 16rpx 20rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.setting-input.small {
|
||
width: 150rpx;
|
||
}
|
||
|
||
.setting-textarea {
|
||
width: 100%;
|
||
min-height: 80rpx;
|
||
padding: 16rpx 20rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
box-sizing: border-box;
|
||
resize: vertical;
|
||
}
|
||
|
||
.setting-select {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 16rpx 20rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 8rpx;
|
||
background-color: #fff;
|
||
cursor: pointer;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.switch-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15rpx;
|
||
}
|
||
|
||
.switch-text {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.checkbox-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.checkbox-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.image-upload {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.upload-area {
|
||
width: 120rpx;
|
||
height: 60rpx;
|
||
border: 2rpx dashed #ddd;
|
||
border-radius: 8rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
color: #999;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.upload-text {
|
||
font-size: 22rpx;
|
||
margin-left: 8rpx;
|
||
}
|
||
|
||
.preview-image {
|
||
width: 120rpx;
|
||
height: 60rpx;
|
||
border-radius: 8rpx;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.settings-footer {
|
||
margin-top: 40rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
justify-content: center;
|
||
}
|
||
|
||
.btn-primary {
|
||
background-color: #1890ff;
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 8rpx;
|
||
padding: 16rpx 40rpx;
|
||
font-size: 28rpx;
|
||
cursor: pointer;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.btn-secondary {
|
||
background-color: #fff;
|
||
color: #666;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 8rpx;
|
||
padding: 16rpx 40rpx;
|
||
font-size: 28rpx;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.iconfont {
|
||
font-family: 'iconfont';
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media screen and (max-width: 750rpx) {
|
||
.settings-nav {
|
||
padding: 15rpx;
|
||
}
|
||
|
||
.nav-item {
|
||
padding: 15rpx 20rpx;
|
||
margin-right: 10rpx;
|
||
min-width: 100rpx;
|
||
}
|
||
|
||
.setting-item {
|
||
flex-direction: column;
|
||
gap: 15rpx;
|
||
}
|
||
|
||
.item-info {
|
||
margin-right: 0;
|
||
}
|
||
|
||
.item-control {
|
||
min-width: auto;
|
||
}
|
||
|
||
.setting-input.small {
|
||
width: 100%;
|
||
}
|
||
|
||
.checkbox-group {
|
||
flex-direction: column;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.action-buttons {
|
||
flex-direction: column;
|
||
gap: 15rpx;
|
||
}
|
||
|
||
.btn-primary,
|
||
.btn-secondary {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style> |