主要更新: - 后台菜单精简(9项→6项) - 新增搜索功能(敏感信息过滤) - 分销绑定和提现系统完善 - 数据库初始化API(自动修复表结构) - 用户管理:显示绑定关系详情 - 小程序:上下章导航优化、匹配页面重构 - 修复hydration和数据类型问题
301 lines
7.5 KiB
TypeScript
301 lines
7.5 KiB
TypeScript
/**
|
|
* 系统配置API
|
|
* 优先读取数据库配置,失败时读取本地默认配置
|
|
* 支持配置的增删改查
|
|
*/
|
|
|
|
import { NextRequest, NextResponse } from 'next/server'
|
|
import { query, getConfig, setConfig } from '@/lib/db'
|
|
|
|
// 本地默认配置(作为数据库备份)
|
|
const DEFAULT_CONFIGS: Record<string, any> = {
|
|
// 站点配置
|
|
site_config: {
|
|
siteName: 'Soul创业派对',
|
|
siteDescription: '来自派对房的真实商业故事',
|
|
logo: '/icon.svg',
|
|
keywords: ['创业', 'Soul', '私域运营', '商业案例'],
|
|
icp: '',
|
|
analytics: ''
|
|
},
|
|
|
|
// 匹配功能配置
|
|
match_config: {
|
|
matchTypes: [
|
|
{ id: 'partner', label: '创业合伙', matchLabel: '创业伙伴', icon: '⭐', matchFromDB: true, showJoinAfterMatch: false, enabled: true },
|
|
{ id: 'investor', label: '资源对接', matchLabel: '资源对接', icon: '👥', matchFromDB: false, showJoinAfterMatch: true, enabled: true },
|
|
{ id: 'mentor', label: '导师顾问', matchLabel: '商业顾问', icon: '❤️', matchFromDB: false, showJoinAfterMatch: true, enabled: true },
|
|
{ id: 'team', label: '团队招募', matchLabel: '加入项目', icon: '🎮', matchFromDB: false, showJoinAfterMatch: true, enabled: true }
|
|
],
|
|
freeMatchLimit: 3,
|
|
matchPrice: 1,
|
|
settings: {
|
|
enableFreeMatches: true,
|
|
enablePaidMatches: true,
|
|
maxMatchesPerDay: 10
|
|
}
|
|
},
|
|
|
|
// 分销配置
|
|
referral_config: {
|
|
distributorShare: 90,
|
|
minWithdrawAmount: 10,
|
|
bindingDays: 30,
|
|
userDiscount: 5,
|
|
enableAutoWithdraw: false
|
|
},
|
|
|
|
// 价格配置
|
|
price_config: {
|
|
sectionPrice: 1,
|
|
fullBookPrice: 9.9,
|
|
premiumBookPrice: 19.9,
|
|
matchPrice: 1
|
|
},
|
|
|
|
// 支付配置
|
|
payment_config: {
|
|
wechat: {
|
|
enabled: true,
|
|
appId: 'wx432c93e275548671',
|
|
mchId: '1318592501'
|
|
},
|
|
alipay: {
|
|
enabled: true,
|
|
pid: '2088511801157159'
|
|
},
|
|
wechatGroupUrl: '' // 支付成功后跳转的微信群链接
|
|
},
|
|
|
|
// 书籍配置
|
|
book_config: {
|
|
totalSections: 62,
|
|
freeSections: ['preface', 'epilogue', '1.1', 'appendix-1', 'appendix-2', 'appendix-3'],
|
|
latestSectionId: '9.14'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GET - 获取配置
|
|
* 参数: key - 配置键名,不传则返回所有配置
|
|
*/
|
|
export async function GET(request: NextRequest) {
|
|
const { searchParams } = new URL(request.url)
|
|
const key = searchParams.get('key')
|
|
const forceLocal = searchParams.get('forceLocal') === 'true'
|
|
|
|
try {
|
|
if (key) {
|
|
// 获取单个配置
|
|
let config = null
|
|
|
|
if (!forceLocal) {
|
|
// 优先从数据库读取
|
|
try {
|
|
config = await getConfig(key)
|
|
} catch (e) {
|
|
console.log(`[Config API] 数据库读取${key}失败,使用本地配置`)
|
|
}
|
|
}
|
|
|
|
// 数据库没有则使用本地默认
|
|
if (!config) {
|
|
config = DEFAULT_CONFIGS[key] || null
|
|
}
|
|
|
|
if (config) {
|
|
return NextResponse.json({
|
|
success: true,
|
|
key,
|
|
config,
|
|
source: config === DEFAULT_CONFIGS[key] ? 'local' : 'database'
|
|
})
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '配置不存在'
|
|
}, { status: 404 })
|
|
}
|
|
|
|
// 获取所有配置
|
|
const allConfigs: Record<string, any> = {}
|
|
const sources: Record<string, string> = {}
|
|
|
|
for (const configKey of Object.keys(DEFAULT_CONFIGS)) {
|
|
let config = null
|
|
|
|
if (!forceLocal) {
|
|
try {
|
|
config = await getConfig(configKey)
|
|
} catch (e) {
|
|
// 忽略数据库错误
|
|
}
|
|
}
|
|
|
|
if (config) {
|
|
allConfigs[configKey] = config
|
|
sources[configKey] = 'database'
|
|
} else {
|
|
allConfigs[configKey] = DEFAULT_CONFIGS[configKey]
|
|
sources[configKey] = 'local'
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
configs: allConfigs,
|
|
sources
|
|
})
|
|
|
|
} catch (error) {
|
|
console.error('[Config API] GET错误:', error)
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '获取配置失败: ' + (error as Error).message
|
|
}, { status: 500 })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST - 保存配置到数据库
|
|
*/
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json()
|
|
const { key, config, description } = body
|
|
|
|
if (!key || !config) {
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '配置键名和配置值不能为空'
|
|
}, { status: 400 })
|
|
}
|
|
|
|
// 保存到数据库
|
|
const success = await setConfig(key, config, description)
|
|
|
|
if (success) {
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: '配置保存成功',
|
|
key
|
|
})
|
|
} else {
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '配置保存失败'
|
|
}, { status: 500 })
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('[Config API] POST错误:', error)
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '保存配置失败: ' + (error as Error).message
|
|
}, { status: 500 })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PUT - 批量更新配置
|
|
*/
|
|
export async function PUT(request: NextRequest) {
|
|
try {
|
|
const body = await request.json()
|
|
const { configs } = body
|
|
|
|
if (!configs || typeof configs !== 'object') {
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '配置数据格式错误'
|
|
}, { status: 400 })
|
|
}
|
|
|
|
let successCount = 0
|
|
let failedCount = 0
|
|
|
|
for (const [key, config] of Object.entries(configs)) {
|
|
try {
|
|
const success = await setConfig(key, config)
|
|
if (success) {
|
|
successCount++
|
|
} else {
|
|
failedCount++
|
|
}
|
|
} catch (e) {
|
|
failedCount++
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: `配置更新完成:成功${successCount}个,失败${failedCount}个`,
|
|
successCount,
|
|
failedCount
|
|
})
|
|
|
|
} catch (error) {
|
|
console.error('[Config API] PUT错误:', error)
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '更新配置失败: ' + (error as Error).message
|
|
}, { status: 500 })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DELETE - 删除配置(恢复为本地默认)
|
|
*/
|
|
export async function DELETE(request: NextRequest) {
|
|
const { searchParams } = new URL(request.url)
|
|
const key = searchParams.get('key')
|
|
|
|
if (!key) {
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '配置键名不能为空'
|
|
}, { status: 400 })
|
|
}
|
|
|
|
try {
|
|
await query('DELETE FROM system_config WHERE config_key = ?', [key])
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: '配置已删除,将使用本地默认值',
|
|
key
|
|
})
|
|
|
|
} catch (error) {
|
|
console.error('[Config API] DELETE错误:', error)
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: '删除配置失败: ' + (error as Error).message
|
|
}, { status: 500 })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 初始化:将本地配置同步到数据库
|
|
*/
|
|
export async function syncLocalToDatabase() {
|
|
console.log('[Config] 开始同步本地配置到数据库...')
|
|
|
|
for (const [key, config] of Object.entries(DEFAULT_CONFIGS)) {
|
|
try {
|
|
// 检查数据库是否已有该配置
|
|
const existing = await getConfig(key)
|
|
if (!existing) {
|
|
// 数据库没有,则写入
|
|
await setConfig(key, config, `默认${key}配置`)
|
|
console.log(`[Config] 同步配置: ${key}`)
|
|
}
|
|
} catch (e) {
|
|
console.error(`[Config] 同步${key}失败:`, e)
|
|
}
|
|
}
|
|
|
|
console.log('[Config] 配置同步完成')
|
|
}
|