Files
soul/app/api/db/init/route.ts
卡若 4dd2f9f4a7 feat: 完善后台管理+搜索功能+分销系统
主要更新:
- 后台菜单精简(9项→6项)
- 新增搜索功能(敏感信息过滤)
- 分销绑定和提现系统完善
- 数据库初始化API(自动修复表结构)
- 用户管理:显示绑定关系详情
- 小程序:上下章导航优化、匹配页面重构
- 修复hydration和数据类型问题
2026-01-25 19:37:59 +08:00

174 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 数据库初始化/升级API
* 用于添加缺失的字段,确保表结构完整
*/
import { NextRequest, NextResponse } from 'next/server'
import { query } from '@/lib/db'
/**
* GET - 初始化/升级数据库表结构
*/
export async function GET(request: NextRequest) {
const results: string[] = []
try {
console.log('[DB Init] 开始检查并升级数据库结构...')
// 1. 检查users表是否存在
try {
await query('SELECT 1 FROM users LIMIT 1')
results.push('✅ users表已存在')
} catch (e) {
// 创建users表
await query(`
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(50) PRIMARY KEY,
open_id VARCHAR(100) UNIQUE,
session_key VARCHAR(100),
nickname VARCHAR(100),
avatar VARCHAR(500),
phone VARCHAR(20),
password VARCHAR(100),
wechat_id VARCHAR(100),
referral_code VARCHAR(20) UNIQUE,
referred_by VARCHAR(50),
purchased_sections JSON DEFAULT '[]',
has_full_book BOOLEAN DEFAULT FALSE,
is_admin BOOLEAN DEFAULT FALSE,
earnings DECIMAL(10,2) DEFAULT 0,
pending_earnings DECIMAL(10,2) DEFAULT 0,
withdrawn_earnings DECIMAL(10,2) DEFAULT 0,
referral_count INT DEFAULT 0,
match_count_today INT DEFAULT 0,
last_match_date DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`)
results.push('✅ 创建users表')
}
// 2. 修改open_id字段允许NULL后台添加用户时可能没有openId
try {
await query('ALTER TABLE users MODIFY COLUMN open_id VARCHAR(100) NULL')
results.push('✅ 修改open_id允许NULL')
} catch (e: any) {
results.push(`⏭️ open_id字段: ${e.message?.includes('Duplicate') ? '已处理' : e.message}`)
}
// 3. 添加可能缺失的字段用ALTER TABLE
const columnsToAdd = [
{ name: 'password', type: 'VARCHAR(100)' },
{ name: 'session_key', type: 'VARCHAR(100)' },
{ name: 'referred_by', type: 'VARCHAR(50)' },
{ name: 'is_admin', type: 'BOOLEAN DEFAULT FALSE' },
{ name: 'match_count_today', type: 'INT DEFAULT 0' },
{ name: 'last_match_date', type: 'DATE' },
{ name: 'withdrawn_earnings', type: 'DECIMAL(10,2) DEFAULT 0' },
{ name: 'avatar', type: 'VARCHAR(500)' },
{ name: 'wechat_id', type: 'VARCHAR(100)' }
]
for (const col of columnsToAdd) {
try {
// 先检查列是否存在
const checkResult = await query(`
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = ?
`, [col.name]) as any[]
if (checkResult.length === 0) {
// 列不存在,添加
await query(`ALTER TABLE users ADD COLUMN ${col.name} ${col.type}`)
results.push(`✅ 添加字段: ${col.name}`)
} else {
results.push(`⏭️ 字段已存在: ${col.name}`)
}
} catch (e: any) {
results.push(`⚠️ 处理字段${col.name}时出错: ${e.message}`)
}
}
// 3. 添加索引(如果不存在)
const indexesToAdd = [
{ name: 'idx_open_id', column: 'open_id' },
{ name: 'idx_phone', column: 'phone' },
{ name: 'idx_referral_code', column: 'referral_code' },
{ name: 'idx_referred_by', column: 'referred_by' }
]
for (const idx of indexesToAdd) {
try {
const checkResult = await query(`
SHOW INDEX FROM users WHERE Key_name = ?
`, [idx.name]) as any[]
if (checkResult.length === 0) {
await query(`CREATE INDEX ${idx.name} ON users(${idx.column})`)
results.push(`✅ 添加索引: ${idx.name}`)
}
} catch (e: any) {
// 忽略索引错误
}
}
// 4. 检查提现记录表
try {
await query('SELECT 1 FROM withdrawals LIMIT 1')
results.push('✅ withdrawals表已存在')
} catch (e) {
await query(`
CREATE TABLE IF NOT EXISTS withdrawals (
id VARCHAR(50) PRIMARY KEY,
user_id VARCHAR(50) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
status ENUM('pending', 'processing', 'success', 'failed') DEFAULT 'pending',
wechat_openid VARCHAR(100),
transaction_id VARCHAR(100),
error_message VARCHAR(500),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
processed_at TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`)
results.push('✅ 创建withdrawals表')
}
// 5. 检查系统配置表
try {
await query('SELECT 1 FROM system_config LIMIT 1')
results.push('✅ system_config表已存在')
} catch (e) {
await query(`
CREATE TABLE IF NOT EXISTS system_config (
id INT AUTO_INCREMENT PRIMARY KEY,
config_key VARCHAR(100) UNIQUE NOT NULL,
config_value JSON NOT NULL,
description VARCHAR(200),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`)
results.push('✅ 创建system_config表')
}
console.log('[DB Init] 数据库升级完成')
return NextResponse.json({
success: true,
message: '数据库初始化/升级完成',
results
})
} catch (error) {
console.error('[DB Init] 错误:', error)
return NextResponse.json({
success: false,
error: '数据库初始化失败: ' + (error as Error).message,
results
}, { status: 500 })
}
}