chore: 以本地为准,上传全部并替换 GitHub

This commit is contained in:
卡若
2026-02-03 11:36:53 +08:00
parent 1219166526
commit b404bf546e
131 changed files with 37618 additions and 3930 deletions

View File

@@ -1,25 +1,195 @@
import { NextResponse } from "next/server"
import { getDatabases, getDatabaseStructure } from "@/lib/mongodb-mock-connector" // 更新导入路径
import { NextRequest, NextResponse } from 'next/server'
import { getMongoClient } from '@/lib/mongodb'
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
const database = searchParams.get("database")
if (database) {
// 获取指定数据库的结构
const structure = await getDatabaseStructure(database)
return NextResponse.json({ success: true, data: structure })
} else {
// 获取所有数据库列表
const databases = await getDatabases()
return NextResponse.json({ success: true, data: databases })
// 获取所有数据库结构
async function getDatabaseStructure() {
const client = await getMongoClient()
const admin = client.db().admin()
// 获取数据库列表
const dbList = await admin.listDatabases()
const krDatabases = dbList.databases.filter(db => db.name.startsWith('KR'))
const structure = []
for (const dbInfo of krDatabases.slice(0, 10)) { // 限制前10个
try {
const db = client.db(dbInfo.name)
const collections = await db.listCollections().toArray()
// 获取每个集合的字段示例
const collectionDetails = []
for (const col of collections.slice(0, 5)) { // 每个库最多5个集合
try {
const sample = await db.collection(col.name).findOne()
const fields = sample ? Object.keys(sample).filter(k => k !== '_id').slice(0, 10) : []
const count = await db.collection(col.name).estimatedDocumentCount()
collectionDetails.push({
name: col.name,
fields,
count
})
} catch {
// 忽略错误
}
}
structure.push({
database: dbInfo.name,
sizeGB: (dbInfo.sizeOnDisk / 1024 / 1024 / 1024).toFixed(2),
collections: collectionDetails
})
} catch {
// 忽略错误
}
}
return structure
}
// 生成血缘节点
function generateLineageNodes(structure: any[]) {
const nodes: any[] = []
const connections: any[] = []
let yOffset = 50
// 数据源节点 (左侧)
const colors = [
'from-blue-400 to-blue-600',
'from-orange-400 to-orange-600',
'from-green-400 to-green-600',
'from-red-400 to-red-600',
'from-purple-400 to-purple-600',
]
structure.forEach((db, i) => {
const mainCol = db.collections[0]
if (!mainCol) return
nodes.push({
id: `source_${db.database}`,
type: 'source',
name: db.database.replace('KR_', ''),
database: db.database,
collection: mainCol.name,
fields: mainCol.fields.slice(0, 5),
x: 50,
y: yOffset,
color: colors[i % colors.length],
count: mainCol.count,
sizeGB: db.sizeGB
})
yOffset += 140
})
// AI引擎节点 (中间)
nodes.push({
id: 'transform_ai',
type: 'transform',
name: 'AI标签引擎',
fields: ['phone_norm', 'qq_norm', 'rfm_score', 'user_level', 'tags'],
x: 400,
y: 150,
color: 'from-violet-400 to-violet-600'
})
nodes.push({
id: 'transform_clean',
type: 'transform',
name: '数据清洗',
fields: ['unique_id', 'merged_data', 'quality'],
x: 400,
y: 350,
color: 'from-yellow-400 to-yellow-600'
})
// 目标节点 (右侧)
nodes.push({
id: 'target_valuation',
type: 'target',
name: '用户估值',
database: 'KR',
collection: '用户估值',
fields: ['phone', 'qq', 'rfm_score', 'user_level', 'tags'],
x: 750,
y: 200,
color: 'from-emerald-400 to-emerald-600'
})
nodes.push({
id: 'target_portrait',
type: 'target',
name: '用户画像',
database: 'KR',
collection: '用户画像',
fields: ['user_id', 'portrait', 'behavior'],
x: 750,
y: 400,
color: 'from-cyan-400 to-cyan-600'
})
// 自动生成连接
structure.forEach(db => {
const sourceId = `source_${db.database}`
const mainCol = db.collections[0]
if (!mainCol) return
// 连接到AI引擎
if (mainCol.fields.includes('phone') || mainCol.fields.includes('手机')) {
connections.push({
id: `conn_${sourceId}_phone`,
sourceNode: sourceId,
sourceField: mainCol.fields.includes('phone') ? 'phone' : '手机',
targetNode: 'transform_ai',
targetField: 'phone_norm'
})
}
if (mainCol.fields.includes('qq') || mainCol.fields.includes('QQ')) {
connections.push({
id: `conn_${sourceId}_qq`,
sourceNode: sourceId,
sourceField: mainCol.fields.includes('qq') ? 'qq' : 'QQ',
targetNode: 'transform_ai',
targetField: 'qq_norm'
})
}
})
// AI引擎到目标
connections.push({
id: 'conn_ai_valuation',
sourceNode: 'transform_ai',
sourceField: 'rfm_score',
targetNode: 'target_valuation',
targetField: 'rfm_score'
})
connections.push({
id: 'conn_clean_portrait',
sourceNode: 'transform_clean',
sourceField: 'merged_data',
targetNode: 'target_portrait',
targetField: 'portrait'
})
return { nodes, connections }
}
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const action = searchParams.get('action') || 'structure'
try {
const structure = await getDatabaseStructure()
if (action === 'lineage') {
const lineage = generateLineageNodes(structure)
return NextResponse.json({ success: true, ...lineage })
}
return NextResponse.json({ success: true, databases: structure })
} catch (error) {
console.error("数据库结构查询失败:", error)
return NextResponse.json(
{ success: false, message: "数据库结构查询失败", error: (error as Error).message },
{ status: 500 },
)
console.error('数据库结构查询失败:', error)
return NextResponse.json({ error: '查询失败' }, { status: 500 })
}
}