400 lines
11 KiB
TypeScript
400 lines
11 KiB
TypeScript
import { supabase } from './useSupabase'
|
|
|
|
// 新增订单相关接口
|
|
export interface Order {
|
|
id?: string
|
|
user_id?: string
|
|
interpreter_id?: string
|
|
type: string // 服务类型
|
|
status: 'pending' | 'confirmed' | 'in_progress' | 'completed' | 'cancelled'
|
|
source_language: string
|
|
target_language: string
|
|
scheduled_date?: string
|
|
duration?: number
|
|
service_address?: string
|
|
special_requirements?: string
|
|
total_amount?: number
|
|
payment_status: 'pending' | 'paid' | 'failed'
|
|
created_at?: string
|
|
updated_at?: string
|
|
|
|
// 扩展字段(用于前端显示)
|
|
order_number?: string
|
|
client_name?: string
|
|
client_email?: string
|
|
client_phone?: string
|
|
client_company?: string
|
|
project_name?: string
|
|
project_description?: string
|
|
urgency?: string
|
|
expected_duration?: number
|
|
estimated_cost?: number
|
|
actual_cost?: number
|
|
interpreter_name?: string
|
|
scheduled_time?: string
|
|
start_time?: string
|
|
end_time?: string
|
|
notes?: string
|
|
}
|
|
|
|
// 新增费率配置接口
|
|
export interface ServiceRate {
|
|
id: string
|
|
service_type: 'audio' | 'video' | 'text'
|
|
language_pair: string
|
|
base_rate: number
|
|
urgency_multiplier: {
|
|
normal: number
|
|
urgent: number
|
|
emergency: number
|
|
}
|
|
minimum_charge: number
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
// 费率计算组合式函数
|
|
export const useRateCalculation = () => {
|
|
// 默认费率配置
|
|
const defaultRates: Record<string, ServiceRate> = {
|
|
'zh-en': {
|
|
id: '1',
|
|
service_type: 'audio',
|
|
language_pair: 'zh-en',
|
|
base_rate: 50,
|
|
urgency_multiplier: { normal: 1, urgent: 1.5, emergency: 2 },
|
|
minimum_charge: 100,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
},
|
|
'en-zh': {
|
|
id: '2',
|
|
service_type: 'video',
|
|
language_pair: 'en-zh',
|
|
base_rate: 60,
|
|
urgency_multiplier: { normal: 1, urgent: 1.5, emergency: 2 },
|
|
minimum_charge: 120,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
}
|
|
}
|
|
|
|
const calculateOrderCost = (
|
|
serviceType: string,
|
|
sourceLanguage: string,
|
|
targetLanguage: string,
|
|
urgency: 'normal' | 'urgent' | 'emergency',
|
|
duration: number = 60
|
|
): number => {
|
|
const languagePair = `${sourceLanguage}-${targetLanguage}`
|
|
const rate = defaultRates[languagePair] || defaultRates['zh-en']
|
|
|
|
const baseRate = rate.base_rate
|
|
const multiplier = rate.urgency_multiplier[urgency]
|
|
const minimumCharge = rate.minimum_charge
|
|
|
|
const calculatedCost = Math.ceil((duration / 60) * baseRate * multiplier)
|
|
return Math.max(calculatedCost, minimumCharge)
|
|
}
|
|
|
|
return {
|
|
defaultRates,
|
|
calculateOrderCost
|
|
}
|
|
}
|
|
|
|
// Supabase数据操作
|
|
export const useSupabaseData = () => {
|
|
const { calculateOrderCost } = useRateCalculation()
|
|
|
|
// 获取所有订单
|
|
const getOrders = async (): Promise<Order[]> => {
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.select(`
|
|
*,
|
|
user:profiles!orders_user_id_fkey(full_name, email, phone),
|
|
interpreter:interpreters!orders_interpreter_id_fkey(name)
|
|
`)
|
|
.order('created_at', { ascending: false })
|
|
|
|
if (error) {
|
|
console.error('获取订单失败:', error)
|
|
return []
|
|
}
|
|
|
|
// 转换数据格式以适配前端
|
|
return data?.map(order => ({
|
|
...order,
|
|
order_number: `ORD${new Date(order.created_at).getFullYear()}${String(new Date(order.created_at).getMonth() + 1).padStart(2, '0')}${String(new Date(order.created_at).getDate()).padStart(2, '0')}${order.id?.slice(0, 6).toUpperCase()}`,
|
|
client_name: order.user?.full_name || '未知客户',
|
|
client_email: order.user?.email || '',
|
|
client_phone: order.user?.phone || '',
|
|
project_name: order.special_requirements ? `${order.type}服务` : `${order.source_language}-${order.target_language}翻译`,
|
|
project_description: order.special_requirements || `${order.source_language}到${order.target_language}的${order.type}服务`,
|
|
interpreter_name: order.interpreter?.name || null,
|
|
estimated_cost: order.total_amount,
|
|
actual_cost: order.payment_status === 'paid' ? order.total_amount : null,
|
|
scheduled_time: order.scheduled_date ? new Date(order.scheduled_date).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }) : null,
|
|
notes: order.special_requirements
|
|
})) || []
|
|
}
|
|
|
|
// 根据ID获取订单
|
|
const getOrderById = async (id: string): Promise<Order | null> => {
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.select('*')
|
|
.eq('id', id)
|
|
.single()
|
|
|
|
if (error) throw error
|
|
return data
|
|
} catch (error) {
|
|
console.error('获取订单详情失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
// 创建新订单
|
|
const createOrder = async (orderData: Partial<Order>): Promise<Order | null> => {
|
|
try {
|
|
// 生成订单号
|
|
const now = new Date()
|
|
const orderNumber = `ORD${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}${String(Math.floor(Math.random() * 1000)).padStart(3, '0')}`
|
|
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.insert([{
|
|
type: orderData.type || 'interpretation',
|
|
status: 'pending',
|
|
source_language: orderData.source_language || 'zh',
|
|
target_language: orderData.target_language || 'en',
|
|
scheduled_date: orderData.scheduled_date ? new Date(orderData.scheduled_date + 'T' + (orderData.scheduled_time || '09:00')).toISOString() : null,
|
|
duration: orderData.expected_duration || orderData.duration,
|
|
service_address: orderData.service_address,
|
|
special_requirements: orderData.notes || orderData.special_requirements,
|
|
total_amount: orderData.estimated_cost || orderData.total_amount,
|
|
payment_status: 'pending'
|
|
}])
|
|
.select()
|
|
|
|
if (error) throw error
|
|
return data?.[0]
|
|
} catch (error) {
|
|
console.error('创建订单失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
// 更新订单
|
|
const updateOrder = async (orderId: string, updates: Partial<Order>): Promise<Order | null> => {
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.update({
|
|
...updates,
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq('id', orderId)
|
|
.select()
|
|
|
|
if (error) throw error
|
|
return data?.[0]
|
|
} catch (error) {
|
|
console.error('更新订单失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
// 删除订单
|
|
const deleteOrder = async (orderId: string): Promise<boolean> => {
|
|
try {
|
|
const { error } = await supabase
|
|
.from('orders')
|
|
.delete()
|
|
.eq('id', orderId)
|
|
|
|
if (error) throw error
|
|
return true
|
|
} catch (error) {
|
|
console.error('删除订单失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 分配口译员
|
|
const assignInterpreter = async (orderId: string, interpreterId: string, interpreterName: string): Promise<boolean> => {
|
|
try {
|
|
const { error } = await supabase
|
|
.from('orders')
|
|
.update({
|
|
interpreter_id: interpreterId,
|
|
interpreter_name: interpreterName,
|
|
status: 'confirmed',
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq('id', orderId)
|
|
|
|
if (error) throw error
|
|
return true
|
|
} catch (error) {
|
|
console.error('分配口译员失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 更新订单状态
|
|
const updateOrderStatus = async (orderId: string, status: Order['status']): Promise<boolean> => {
|
|
try {
|
|
const { error } = await supabase
|
|
.from('orders')
|
|
.update({
|
|
status,
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq('id', orderId)
|
|
|
|
if (error) throw error
|
|
return true
|
|
} catch (error) {
|
|
console.error('更新订单状态失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 获取订单统计
|
|
const getOrderStats = async (): Promise<{
|
|
total: number
|
|
pending: number
|
|
inProgress: number
|
|
completed: number
|
|
cancelled: number
|
|
totalRevenue: number
|
|
}> => {
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.select('status, total_amount, payment_status')
|
|
|
|
if (error) {
|
|
console.error('获取订单统计失败:', error)
|
|
return {
|
|
total: 0,
|
|
pending: 0,
|
|
inProgress: 0,
|
|
completed: 0,
|
|
cancelled: 0,
|
|
totalRevenue: 0
|
|
}
|
|
}
|
|
|
|
const stats = {
|
|
total: data?.length || 0,
|
|
pending: data?.filter(o => o.status === 'pending').length || 0,
|
|
inProgress: data?.filter(o => o.status === 'in_progress').length || 0,
|
|
completed: data?.filter(o => o.status === 'completed').length || 0,
|
|
cancelled: data?.filter(o => o.status === 'cancelled').length || 0,
|
|
totalRevenue: data?.filter(o => o.payment_status === 'paid').reduce((sum, o) => sum + (Number(o.total_amount) || 0), 0) || 0
|
|
}
|
|
|
|
return stats
|
|
}
|
|
|
|
// 获取服务费率
|
|
const getServiceRates = async (): Promise<ServiceRate[]> => {
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('service_rates')
|
|
.select('*')
|
|
.order('created_at', { ascending: false })
|
|
|
|
if (error) throw error
|
|
return data || []
|
|
} catch (error) {
|
|
console.error('获取服务费率失败:', error)
|
|
return []
|
|
}
|
|
}
|
|
|
|
// 创建服务费率
|
|
const createServiceRate = async (rateData: Partial<ServiceRate>): Promise<ServiceRate | null> => {
|
|
try {
|
|
const newRate = {
|
|
...rateData,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
}
|
|
|
|
const { data, error } = await supabase
|
|
.from('service_rates')
|
|
.insert([newRate])
|
|
.select()
|
|
.single()
|
|
|
|
if (error) throw error
|
|
return data
|
|
} catch (error) {
|
|
console.error('创建服务费率失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
// 更新服务费率
|
|
const updateServiceRate = async (id: string, updates: Partial<ServiceRate>): Promise<ServiceRate | null> => {
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('service_rates')
|
|
.update({
|
|
...updates,
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq('id', id)
|
|
.select()
|
|
.single()
|
|
|
|
if (error) throw error
|
|
return data
|
|
} catch (error) {
|
|
console.error('更新服务费率失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
// 删除服务费率
|
|
const deleteServiceRate = async (id: string): Promise<boolean> => {
|
|
try {
|
|
const { error } = await supabase
|
|
.from('service_rates')
|
|
.delete()
|
|
.eq('id', id)
|
|
|
|
if (error) throw error
|
|
return true
|
|
} catch (error) {
|
|
console.error('删除服务费率失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
return {
|
|
// 订单相关方法
|
|
getOrders,
|
|
getOrderById,
|
|
createOrder,
|
|
updateOrder,
|
|
deleteOrder,
|
|
assignInterpreter,
|
|
updateOrderStatus,
|
|
getOrderStats,
|
|
|
|
// 费率相关方法
|
|
getServiceRates,
|
|
createServiceRate,
|
|
updateServiceRate,
|
|
deleteServiceRate,
|
|
|
|
// 费率计算
|
|
calculateOrderCost
|
|
}
|
|
}
|