137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
/**
|
|
* 通用高级查询API接口
|
|
* Universal Advanced Query API Endpoint
|
|
*/
|
|
import type { AdvancedQueryOptions } from '@nuxt4crud/shared'
|
|
import { prisma } from '../lib/prisma'
|
|
import { createSqlQueryBuilder } from '../lib/sql-query-builder'
|
|
|
|
/**
|
|
* 通用查询请求体接口
|
|
* Universal query request body interface
|
|
*/
|
|
interface UniversalQueryRequest {
|
|
table: string
|
|
options: AdvancedQueryOptions
|
|
searchFields?: string[]
|
|
mode?: 'query' | 'aggregate'
|
|
}
|
|
|
|
/**
|
|
* 支持的表名映射(安全检查)
|
|
* Supported table names mapping (security check)
|
|
*/
|
|
const ALLOWED_TABLES = {
|
|
Post: 'posts', // 支持 Post 表
|
|
User: 'users', // 支持 User 表
|
|
// 可以在这里添加更多允许查询的表
|
|
} as const
|
|
|
|
/**
|
|
* 默认搜索字段配置
|
|
* Default search fields configuration
|
|
*/
|
|
const DEFAULT_SEARCH_FIELDS: Record<string, string[]> = {
|
|
posts: ['title', 'content'], // Post 表搜索字段
|
|
users: ['name', 'email'], // User 表搜索字段
|
|
// 可以为其他表配置默认搜索字段
|
|
}
|
|
|
|
/**
|
|
* 通用高级查询API处理器
|
|
* Universal advanced query API handler
|
|
*/
|
|
export default defineEventHandler(async event => {
|
|
try {
|
|
// 只允许POST方法
|
|
assertMethod(event, 'POST')
|
|
|
|
// 获取请求体
|
|
const body = (await readBody(event)) as UniversalQueryRequest
|
|
|
|
// 验证请求参数
|
|
if (!body.table || !body.options) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: '缺少必要参数: table 和 options',
|
|
})
|
|
}
|
|
|
|
// 安全检查:验证表名是否允许
|
|
const tableName = ALLOWED_TABLES[body.table as keyof typeof ALLOWED_TABLES]
|
|
if (!tableName) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: `不允许查询表: ${body.table}`,
|
|
})
|
|
}
|
|
|
|
// 创建SQL查询构造器
|
|
const queryBuilder = createSqlQueryBuilder(prisma)
|
|
|
|
// 获取表字段信息
|
|
const availableFields = await queryBuilder.getTableFields(tableName)
|
|
|
|
// 验证查询选项
|
|
const validationErrors = queryBuilder.validateQueryOptions(body.options, availableFields)
|
|
if (validationErrors.length > 0) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: `查询参数验证失败: ${validationErrors.join(', ')}`,
|
|
})
|
|
}
|
|
|
|
// 获取搜索字段
|
|
const searchFields = body.searchFields || DEFAULT_SEARCH_FIELDS[tableName] || []
|
|
|
|
// 执行查询
|
|
let result: any
|
|
|
|
if (body.mode === 'aggregate') {
|
|
// 执行聚合查询
|
|
result = await queryBuilder.executeAggregateQuery(tableName, body.options)
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
table: tableName,
|
|
mode: 'aggregate',
|
|
result,
|
|
options: body.options,
|
|
availableFields,
|
|
searchFields,
|
|
},
|
|
message: '聚合查询执行成功',
|
|
}
|
|
} else {
|
|
// 执行普通查询
|
|
result = await queryBuilder.executeQuery(tableName, body.options, searchFields)
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
table: tableName,
|
|
mode: 'query',
|
|
...result,
|
|
availableFields,
|
|
searchFields,
|
|
},
|
|
message: '查询执行成功',
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Universal query API error:', error)
|
|
|
|
// 如果是已知错误,直接抛出
|
|
if (error && typeof error === 'object' && 'statusCode' in error) {
|
|
throw error
|
|
}
|
|
|
|
// 处理未知错误
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: `查询执行失败: ${error instanceof Error ? error.message : '未知错误'}`,
|
|
})
|
|
}
|
|
})
|