feat: 集成真实数据库连接和API服务
- 更新 .env.local 配置为真实的 Supabase 项目连接 - 创建完整的 API 服务层 (lib/api-service.ts) - 创建数据库类型定义 (types/database.ts) - 更新仪表盘页面使用真实数据替代演示数据 - 添加数据库连接测试和错误处理 - 创建测试数据验证系统功能 - 修复图标导入和语法错误 系统现在已连接到真实的 Supabase 数据库,可以正常显示统计数据和最近活动。
This commit is contained in:
+671
-2
@@ -1,4 +1,10 @@
|
||||
import { supabase } from './supabase';
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Database } from '../types/database'
|
||||
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
|
||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
|
||||
export const supabase = createClient<Database>(supabaseUrl, supabaseAnonKey)
|
||||
|
||||
// 用户相关接口
|
||||
export interface User {
|
||||
@@ -320,4 +326,667 @@ class ApiService {
|
||||
export const apiService = new ApiService();
|
||||
|
||||
// 导出默认实例
|
||||
export default apiService;
|
||||
export default apiService;
|
||||
|
||||
// 用户相关API
|
||||
export const userAPI = {
|
||||
// 获取用户列表
|
||||
async getUsers(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
user_type?: string
|
||||
status?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('users')
|
||||
.select('*', { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.search) {
|
||||
query = query.or(`name.ilike.%${params.search}%,email.ilike.%${params.search}%`)
|
||||
}
|
||||
|
||||
if (params?.user_type) {
|
||||
query = query.eq('user_type', params.user_type)
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个用户
|
||||
async getUser(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('users')
|
||||
.select('*')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建用户
|
||||
async createUser(userData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('users')
|
||||
.insert([userData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新用户
|
||||
async updateUser(id: string, userData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('users')
|
||||
.update(userData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 删除用户
|
||||
async deleteUser(id: string) {
|
||||
const { error } = await supabase
|
||||
.from('users')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
|
||||
if (error) throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 翻译员相关API
|
||||
export const interpreterAPI = {
|
||||
// 获取翻译员列表
|
||||
async getInterpreters(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
status?: string
|
||||
language?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('interpreters')
|
||||
.select('*', { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.search) {
|
||||
query = query.or(`name.ilike.%${params.search}%,email.ilike.%${params.search}%`)
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
if (params?.language) {
|
||||
query = query.contains('languages', [params.language])
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个翻译员
|
||||
async getInterpreter(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('interpreters')
|
||||
.select('*')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建翻译员
|
||||
async createInterpreter(interpreterData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('interpreters')
|
||||
.insert([interpreterData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新翻译员
|
||||
async updateInterpreter(id: string, interpreterData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('interpreters')
|
||||
.update(interpreterData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 删除翻译员
|
||||
async deleteInterpreter(id: string) {
|
||||
const { error } = await supabase
|
||||
.from('interpreters')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
|
||||
if (error) throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 订单相关API
|
||||
export const orderAPI = {
|
||||
// 获取订单列表
|
||||
async getOrders(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
status?: string
|
||||
service_type?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('orders')
|
||||
.select('*', { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.search) {
|
||||
query = query.or(`order_number.ilike.%${params.search}%,user_name.ilike.%${params.search}%,user_email.ilike.%${params.search}%`)
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
if (params?.service_type) {
|
||||
query = query.eq('service_type', params.service_type)
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个订单
|
||||
async getOrder(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('orders')
|
||||
.select('*')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建订单
|
||||
async createOrder(orderData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('orders')
|
||||
.insert([orderData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新订单
|
||||
async updateOrder(id: string, orderData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('orders')
|
||||
.update(orderData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 删除订单
|
||||
async deleteOrder(id: string) {
|
||||
const { error } = await supabase
|
||||
.from('orders')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
|
||||
if (error) throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 通话记录相关API
|
||||
export const callAPI = {
|
||||
// 获取通话记录列表
|
||||
async getCalls(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
status?: string
|
||||
service_type?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('calls')
|
||||
.select(`
|
||||
*,
|
||||
users(name, email),
|
||||
interpreters(name, email)
|
||||
`, { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
if (params?.service_type) {
|
||||
query = query.eq('service_type', params.service_type)
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个通话记录
|
||||
async getCall(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('calls')
|
||||
.select(`
|
||||
*,
|
||||
users(name, email),
|
||||
interpreters(name, email)
|
||||
`)
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建通话记录
|
||||
async createCall(callData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('calls')
|
||||
.insert([callData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新通话记录
|
||||
async updateCall(id: string, callData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('calls')
|
||||
.update(callData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
// 发票相关API
|
||||
export const invoiceAPI = {
|
||||
// 获取发票列表
|
||||
async getInvoices(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
status?: string
|
||||
invoice_type?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('invoices')
|
||||
.select('*', { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.search) {
|
||||
query = query.or(`invoice_number.ilike.%${params.search}%,user_name.ilike.%${params.search}%,user_email.ilike.%${params.search}%`)
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
if (params?.invoice_type) {
|
||||
query = query.eq('invoice_type', params.invoice_type)
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个发票
|
||||
async getInvoice(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('invoices')
|
||||
.select('*')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建发票
|
||||
async createInvoice(invoiceData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('invoices')
|
||||
.insert([invoiceData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新发票
|
||||
async updateInvoice(id: string, invoiceData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('invoices')
|
||||
.update(invoiceData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 删除发票
|
||||
async deleteInvoice(id: string) {
|
||||
const { error } = await supabase
|
||||
.from('invoices')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
|
||||
if (error) throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 文档相关API
|
||||
export const documentAPI = {
|
||||
// 获取文档列表
|
||||
async getDocuments(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
status?: string
|
||||
file_type?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('documents')
|
||||
.select('*', { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.search) {
|
||||
query = query.or(`filename.ilike.%${params.search}%,original_name.ilike.%${params.search}%`)
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
if (params?.file_type) {
|
||||
query = query.eq('file_type', params.file_type)
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个文档
|
||||
async getDocument(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('documents')
|
||||
.select('*')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建文档
|
||||
async createDocument(documentData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('documents')
|
||||
.insert([documentData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新文档
|
||||
async updateDocument(id: string, documentData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('documents')
|
||||
.update(documentData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 删除文档
|
||||
async deleteDocument(id: string) {
|
||||
const { error } = await supabase
|
||||
.from('documents')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
|
||||
if (error) throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 企业相关API
|
||||
export const enterpriseAPI = {
|
||||
// 获取企业列表
|
||||
async getEnterprises(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
status?: string
|
||||
}) {
|
||||
let query = supabase
|
||||
.from('enterprises')
|
||||
.select('*', { count: 'exact' })
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (params?.search) {
|
||||
query = query.or(`name.ilike.%${params.search}%,contact_email.ilike.%${params.search}%`)
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
query = query.eq('status', params.status)
|
||||
}
|
||||
|
||||
const { data, error, count } = await query
|
||||
.range(
|
||||
((params?.page || 1) - 1) * (params?.limit || 10),
|
||||
(params?.page || 1) * (params?.limit || 10) - 1
|
||||
)
|
||||
|
||||
if (error) throw error
|
||||
return { data, count }
|
||||
},
|
||||
|
||||
// 获取单个企业
|
||||
async getEnterprise(id: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('enterprises')
|
||||
.select('*')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 创建企业
|
||||
async createEnterprise(enterpriseData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('enterprises')
|
||||
.insert([enterpriseData])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新企业
|
||||
async updateEnterprise(id: string, enterpriseData: any) {
|
||||
const { data, error } = await supabase
|
||||
.from('enterprises')
|
||||
.update(enterpriseData)
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 删除企业
|
||||
async deleteEnterprise(id: string) {
|
||||
const { error } = await supabase
|
||||
.from('enterprises')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
|
||||
if (error) throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 统计数据API
|
||||
export const statsAPI = {
|
||||
// 获取仪表盘统计数据
|
||||
async getDashboardStats() {
|
||||
const [
|
||||
{ count: totalUsers },
|
||||
{ count: totalInterpreters },
|
||||
{ count: totalOrders },
|
||||
{ count: totalCalls },
|
||||
{ count: activeUsers },
|
||||
{ count: activeCalls },
|
||||
{ data: recentOrders },
|
||||
{ data: recentCalls }
|
||||
] = await Promise.all([
|
||||
supabase.from('users').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('interpreters').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('orders').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('calls').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('users').select('*', { count: 'exact', head: true }).eq('status', 'active'),
|
||||
supabase.from('calls').select('*', { count: 'exact', head: true }).eq('status', 'connected'),
|
||||
supabase.from('orders').select('*').order('created_at', { ascending: false }).limit(10),
|
||||
supabase.from('calls').select(`
|
||||
*,
|
||||
users(name, email),
|
||||
interpreters(name, email)
|
||||
`).order('created_at', { ascending: false }).limit(10)
|
||||
])
|
||||
|
||||
return {
|
||||
totalUsers: totalUsers || 0,
|
||||
totalInterpreters: totalInterpreters || 0,
|
||||
totalOrders: totalOrders || 0,
|
||||
totalCalls: totalCalls || 0,
|
||||
activeUsers: activeUsers || 0,
|
||||
activeCalls: activeCalls || 0,
|
||||
recentOrders: recentOrders || [],
|
||||
recentCalls: recentCalls || []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 系统设置API
|
||||
export const settingsAPI = {
|
||||
// 获取系统设置
|
||||
async getSettings() {
|
||||
const { data, error } = await supabase
|
||||
.from('system_settings')
|
||||
.select('*')
|
||||
.order('key')
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 获取单个设置
|
||||
async getSetting(key: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('system_settings')
|
||||
.select('*')
|
||||
.eq('key', key)
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
},
|
||||
|
||||
// 更新设置
|
||||
async updateSetting(key: string, value: string, description?: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('system_settings')
|
||||
.upsert([{ key, value, description }])
|
||||
.select()
|
||||
.single()
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user