You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

513 lines
17 KiB

import SiteConfigModel from "../model/site-config"
import { logger } from "@/logger.js"
/**
* 站点配置服务类
* 提供站点配置相关的业务逻辑
*/
class SiteConfigService {
/**
* 获取配置值
* @param {string} key - 配置键
* @param {*} defaultValue - 默认值
* @returns {Promise<*>} 配置值
*/
static async get(key, defaultValue = null) {
try {
const value = await SiteConfigModel.get(key)
return value !== null ? value : defaultValue
} catch (error) {
logger.error(`获取配置失败 (${key}):`, error)
throw error
}
}
/**
* 设置配置值
* @param {string} key - 配置键
* @param {*} value - 配置值
* @returns {Promise<Object>} 配置对象
*/
static async set(key, value) {
try {
// 验证配置键
this.validateConfigKey(key)
// 序列化值
const serializedValue = this.serializeValue(value)
const config = await SiteConfigModel.set(key, serializedValue)
logger.info(`配置设置成功: ${key}`)
return this.formatConfigResponse(config)
} catch (error) {
logger.error(`设置配置失败 (${key}):`, error)
throw error
}
}
/**
* 批量获取配置
* @param {Array} keys - 配置键数组
* @returns {Promise<Object>} 配置对象
*/
static async getMany(keys) {
try {
if (!Array.isArray(keys) || keys.length === 0) {
return {}
}
const configs = await SiteConfigModel.getMany(keys)
// 反序列化值
const result = {}
for (const [key, value] of Object.entries(configs)) {
result[key] = this.deserializeValue(value)
}
return result
} catch (error) {
logger.error(`批量获取配置失败:`, error)
throw error
}
}
/**
* 获取所有配置
* @returns {Promise<Object>} 所有配置
*/
static async getAll() {
try {
const configs = await SiteConfigModel.getAll()
// 反序列化值
const result = {}
for (const [key, value] of Object.entries(configs)) {
result[key] = this.deserializeValue(value)
}
return result
} catch (error) {
logger.error(`获取所有配置失败:`, error)
throw error
}
}
/**
* 批量设置配置
* @param {Object} configs - 配置对象
* @returns {Promise<Array>} 设置结果
*/
static async setMany(configs) {
try {
if (!configs || typeof configs !== 'object') {
throw new Error("配置对象不能为空")
}
const results = []
for (const [key, value] of Object.entries(configs)) {
try {
this.validateConfigKey(key)
const serializedValue = this.serializeValue(value)
const config = await SiteConfigModel.set(key, serializedValue)
results.push(this.formatConfigResponse(config))
} catch (error) {
logger.error(`设置配置失败 (${key}):`, error)
results.push({ key, error: error.message })
}
}
logger.info(`批量设置配置完成: ${Object.keys(configs).length} 个配置`)
return results
} catch (error) {
logger.error(`批量设置配置失败:`, error)
throw error
}
}
/**
* 删除配置
* @param {string} key - 配置键
* @returns {Promise<boolean>} 删除结果
*/
static async delete(key) {
try {
const result = await SiteConfigModel.deleteByKey(key)
logger.info(`配置删除成功: ${key}`)
return result > 0
} catch (error) {
logger.error(`删除配置失败 (${key}):`, error)
throw error
}
}
/**
* 检查配置是否存在
* @param {string} key - 配置键
* @returns {Promise<boolean>} 是否存在
*/
static async has(key) {
try {
return await SiteConfigModel.hasKey(key)
} catch (error) {
logger.error(`检查配置是否存在失败 (${key}):`, error)
throw error
}
}
/**
* 获取配置统计
* @returns {Promise<Object>} 统计信息
*/
static async getStats() {
try {
return await SiteConfigModel.getConfigStats()
} catch (error) {
logger.error(`获取配置统计失败:`, error)
throw error
}
}
/**
* 获取站点基本信息配置
* @returns {Promise<Object>} 站点基本信息
*/
static async getSiteInfo() {
try {
const keys = [
'site_name',
'site_description',
'site_keywords',
'site_author',
'site_url',
'site_logo',
'site_favicon',
'site_theme',
'site_language',
'site_timezone'
]
const configs = await this.getMany(keys)
return {
name: configs.site_name || '我的网站',
description: configs.site_description || '',
keywords: configs.site_keywords || '',
author: configs.site_author || '',
url: configs.site_url || '',
logo: configs.site_logo || '',
favicon: configs.site_favicon || '',
theme: configs.site_theme || 'default',
language: configs.site_language || 'zh-CN',
timezone: configs.site_timezone || 'Asia/Shanghai'
}
} catch (error) {
logger.error(`获取站点基本信息失败:`, error)
throw error
}
}
/**
* 设置站点基本信息配置
* @param {Object} siteInfo - 站点信息
* @returns {Promise<Object>} 设置结果
*/
static async setSiteInfo(siteInfo) {
try {
const configs = {}
if (siteInfo.name) configs.site_name = siteInfo.name
if (siteInfo.description) configs.site_description = siteInfo.description
if (siteInfo.keywords) configs.site_keywords = siteInfo.keywords
if (siteInfo.author) configs.site_author = siteInfo.author
if (siteInfo.url) configs.site_url = siteInfo.url
if (siteInfo.logo) configs.site_logo = siteInfo.logo
if (siteInfo.favicon) configs.site_favicon = siteInfo.favicon
if (siteInfo.theme) configs.site_theme = siteInfo.theme
if (siteInfo.language) configs.site_language = siteInfo.language
if (siteInfo.timezone) configs.site_timezone = siteInfo.timezone
return await this.setMany(configs)
} catch (error) {
logger.error(`设置站点基本信息失败:`, error)
throw error
}
}
/**
* 获取邮件配置
* @returns {Promise<Object>} 邮件配置
*/
static async getEmailConfig() {
try {
const keys = [
'email_host',
'email_port',
'email_secure',
'email_user',
'email_password',
'email_from',
'email_name'
]
const configs = await this.getMany(keys)
return {
host: configs.email_host || '',
port: parseInt(configs.email_port) || 587,
secure: configs.email_secure === 'true',
user: configs.email_user || '',
password: configs.email_password || '',
from: configs.email_from || '',
name: configs.email_name || ''
}
} catch (error) {
logger.error(`获取邮件配置失败:`, error)
throw error
}
}
/**
* 设置邮件配置
* @param {Object} emailConfig - 邮件配置
* @returns {Promise<Object>} 设置结果
*/
static async setEmailConfig(emailConfig) {
try {
const configs = {}
if (emailConfig.host) configs.email_host = emailConfig.host
if (emailConfig.port) configs.email_port = emailConfig.port.toString()
if (emailConfig.secure !== undefined) configs.email_secure = emailConfig.secure.toString()
if (emailConfig.user) configs.email_user = emailConfig.user
if (emailConfig.password) configs.email_password = emailConfig.password
if (emailConfig.from) configs.email_from = emailConfig.from
if (emailConfig.name) configs.email_name = emailConfig.name
return await this.setMany(configs)
} catch (error) {
logger.error(`设置邮件配置失败:`, error)
throw error
}
}
/**
* 获取系统配置
* @returns {Promise<Object>} 系统配置
*/
static async getSystemConfig() {
try {
const keys = [
'maintenance_mode',
'registration_enabled',
'email_verification_required',
'max_upload_size',
'allowed_file_types',
'session_timeout',
'password_min_length',
'login_attempts_limit'
]
const configs = await this.getMany(keys)
return {
maintenanceMode: configs.maintenance_mode === 'true',
registrationEnabled: configs.registration_enabled !== 'false',
emailVerificationRequired: configs.email_verification_required === 'true',
maxUploadSize: parseInt(configs.max_upload_size) || 10485760, // 10MB
allowedFileTypes: configs.allowed_file_types ? configs.allowed_file_types.split(',') : ['jpg', 'jpeg', 'png', 'gif', 'pdf'],
sessionTimeout: parseInt(configs.session_timeout) || 3600, // 1小时
passwordMinLength: parseInt(configs.password_min_length) || 6,
loginAttemptsLimit: parseInt(configs.login_attempts_limit) || 5
}
} catch (error) {
logger.error(`获取系统配置失败:`, error)
throw error
}
}
/**
* 设置系统配置
* @param {Object} systemConfig - 系统配置
* @returns {Promise<Object>} 设置结果
*/
static async setSystemConfig(systemConfig) {
try {
const configs = {}
if (systemConfig.maintenanceMode !== undefined) configs.maintenance_mode = systemConfig.maintenanceMode.toString()
if (systemConfig.registrationEnabled !== undefined) configs.registration_enabled = systemConfig.registrationEnabled.toString()
if (systemConfig.emailVerificationRequired !== undefined) configs.email_verification_required = systemConfig.emailVerificationRequired.toString()
if (systemConfig.maxUploadSize) configs.max_upload_size = systemConfig.maxUploadSize.toString()
if (systemConfig.allowedFileTypes) configs.allowed_file_types = Array.isArray(systemConfig.allowedFileTypes) ? systemConfig.allowedFileTypes.join(',') : systemConfig.allowedFileTypes
if (systemConfig.sessionTimeout) configs.session_timeout = systemConfig.sessionTimeout.toString()
if (systemConfig.passwordMinLength) configs.password_min_length = systemConfig.passwordMinLength.toString()
if (systemConfig.loginAttemptsLimit) configs.login_attempts_limit = systemConfig.loginAttemptsLimit.toString()
return await this.setMany(configs)
} catch (error) {
logger.error(`设置系统配置失败:`, error)
throw error
}
}
/**
* 重置配置为默认值
* @param {Array} keys - 要重置的配置键数组(可选,默认重置所有)
* @returns {Promise<Object>} 重置结果
*/
static async resetToDefaults(keys = null) {
try {
const defaultConfigs = {
site_name: '我的网站',
site_description: '欢迎来到我的网站',
site_keywords: '网站,博客,个人网站',
site_author: '网站管理员',
site_url: 'http://localhost:3000',
site_theme: 'default',
site_language: 'zh-CN',
site_timezone: 'Asia/Shanghai',
maintenance_mode: 'false',
registration_enabled: 'true',
email_verification_required: 'false',
max_upload_size: '10485760',
allowed_file_types: 'jpg,jpeg,png,gif,pdf',
session_timeout: '3600',
password_min_length: '6',
login_attempts_limit: '5'
}
const configsToReset = keys ?
Object.fromEntries(keys.filter(key => defaultConfigs[key]).map(key => [key, defaultConfigs[key]])) :
defaultConfigs
return await this.setMany(configsToReset)
} catch (error) {
logger.error(`重置配置为默认值失败:`, error)
throw error
}
}
/**
* 验证配置键
* @param {string} key - 配置键
*/
static validateConfigKey(key) {
if (!key || typeof key !== 'string') {
throw new Error("配置键不能为空")
}
if (key.length > 100) {
throw new Error("配置键长度不能超过100个字符")
}
if (!/^[a-zA-Z0-9_]+$/.test(key)) {
throw new Error("配置键只能包含字母、数字和下划线")
}
}
/**
* 序列化值
* @param {*} value - 要序列化的值
* @returns {string} 序列化后的字符串
*/
static serializeValue(value) {
if (value === null || value === undefined) {
return ''
}
if (typeof value === 'string') {
return value
}
if (typeof value === 'number' || typeof value === 'boolean') {
return value.toString()
}
return JSON.stringify(value)
}
/**
* 反序列化值
* @param {string} value - 要反序列化的字符串
* @returns {*} 反序列化后的值
*/
static deserializeValue(value) {
if (value === null || value === undefined || value === '') {
return null
}
// 尝试解析为JSON
try {
return JSON.parse(value)
} catch (e) {
// 如果不是有效的JSON,返回原字符串
return value
}
}
/**
* 格式化配置响应数据
* @param {Object} config - 配置数据
* @returns {Object} 格式化后的配置数据
*/
static formatConfigResponse(config) {
return {
...config,
// 确保数字字段为数字类型
id: parseInt(config.id),
// 反序列化值
value: this.deserializeValue(config.value),
// 格式化日期字段
created_at: config.created_at,
updated_at: config.updated_at
}
}
/**
* 导出配置
* @returns {Promise<Object>} 导出的配置
*/
static async exportConfig() {
try {
const configs = await this.getAll()
return {
exported_at: new Date().toISOString(),
configs
}
} catch (error) {
logger.error(`导出配置失败:`, error)
throw error
}
}
/**
* 导入配置
* @param {Object} configData - 配置数据
* @returns {Promise<Object>} 导入结果
*/
static async importConfig(configData) {
try {
if (!configData || !configData.configs) {
throw new Error("无效的配置数据")
}
const results = await this.setMany(configData.configs)
logger.info(`配置导入完成: ${Object.keys(configData.configs).length} 个配置`)
return {
success: results.filter(r => !r.error).length,
failed: results.filter(r => r.error).length,
results
}
} catch (error) {
logger.error(`导入配置失败:`, error)
throw error
}
}
}
export default SiteConfigService
export { SiteConfigService }