// 费率计算和管理的组合函数 import { ref, computed } from 'vue' import { useSupabase } from './useSupabase' // 服务类型费率配置 export interface ServiceRate { id: string service_type: string service_name: string base_price: number // 基础价格 price_per_minute?: number // 按分钟计费 price_per_word?: number // 按字数计费 price_per_page?: number // 按页数计费 urgency_multiplier: { normal: number urgent: number very_urgent: number } language_pair_multiplier: { [key: string]: number // 语言对费率倍数 } currency: string created_at: string updated_at: string } // 订单费用计算结果 export interface CostCalculation { baseCost: number urgencyMultiplier: number languageMultiplier: number totalCost: number breakdown: { basePrice: number urgencyFee: number languageFee: number estimatedDuration?: number estimatedWords?: number } } export const useRateCalculation = () => { const { supabase } = useSupabase() // 默认费率配置 const defaultRates = ref([ { id: 'voice-call', service_type: 'voice', service_name: '语音通话', base_price: 50, price_per_minute: 2.5, urgency_multiplier: { normal: 1.0, urgent: 1.5, very_urgent: 2.0 }, language_pair_multiplier: { 'zh-en': 1.0, 'zh-ja': 1.2, 'zh-ko': 1.2, 'zh-fr': 1.3, 'zh-de': 1.3, 'zh-es': 1.2, 'zh-ru': 1.4, 'en-ja': 1.3, 'en-ko': 1.3, 'en-fr': 1.2, 'en-de': 1.2, 'en-es': 1.1, 'en-ru': 1.4 }, currency: 'CNY', created_at: new Date().toISOString(), updated_at: new Date().toISOString() }, { id: 'video-call', service_type: 'video', service_name: '视频通话', base_price: 80, price_per_minute: 4.0, urgency_multiplier: { normal: 1.0, urgent: 1.5, very_urgent: 2.0 }, language_pair_multiplier: { 'zh-en': 1.0, 'zh-ja': 1.2, 'zh-ko': 1.2, 'zh-fr': 1.3, 'zh-de': 1.3, 'zh-es': 1.2, 'zh-ru': 1.4 }, currency: 'CNY', created_at: new Date().toISOString(), updated_at: new Date().toISOString() }, { id: 'document-translation', service_type: 'document', service_name: '文档翻译', base_price: 100, price_per_word: 0.15, urgency_multiplier: { normal: 1.0, urgent: 1.3, very_urgent: 1.8 }, language_pair_multiplier: { 'zh-en': 1.0, 'zh-ja': 1.2, 'zh-ko': 1.2, 'zh-fr': 1.3, 'zh-de': 1.3, 'zh-es': 1.2, 'zh-ru': 1.4 }, currency: 'CNY', created_at: new Date().toISOString(), updated_at: new Date().toISOString() }, { id: 'interpretation', service_type: 'interpretation', service_name: '口译服务', base_price: 200, price_per_minute: 8.0, urgency_multiplier: { normal: 1.0, urgent: 1.6, very_urgent: 2.2 }, language_pair_multiplier: { 'zh-en': 1.0, 'zh-ja': 1.3, 'zh-ko': 1.3, 'zh-fr': 1.4, 'zh-de': 1.4, 'zh-es': 1.3, 'zh-ru': 1.5 }, currency: 'CNY', created_at: new Date().toISOString(), updated_at: new Date().toISOString() }, { id: 'localization', service_type: 'localization', service_name: '本地化', base_price: 300, price_per_word: 0.25, urgency_multiplier: { normal: 1.0, urgent: 1.4, very_urgent: 1.9 }, language_pair_multiplier: { 'zh-en': 1.0, 'zh-ja': 1.3, 'zh-ko': 1.3, 'zh-fr': 1.4, 'zh-de': 1.4, 'zh-es': 1.3, 'zh-ru': 1.5 }, currency: 'CNY', created_at: new Date().toISOString(), updated_at: new Date().toISOString() }, { id: 'proofreading', service_type: 'proofreading', service_name: '校对服务', base_price: 80, price_per_word: 0.08, urgency_multiplier: { normal: 1.0, urgent: 1.3, very_urgent: 1.7 }, language_pair_multiplier: { 'zh-en': 1.0, 'zh-ja': 1.1, 'zh-ko': 1.1, 'zh-fr': 1.2, 'zh-de': 1.2, 'zh-es': 1.1, 'zh-ru': 1.3 }, currency: 'CNY', created_at: new Date().toISOString(), updated_at: new Date().toISOString() } ]) // 当前费率配置 const serviceRates = ref([]) const loading = ref(false) const error = ref(null) // 从数据库加载费率配置 const loadRates = async () => { loading.value = true error.value = null try { const { data, error: dbError } = await supabase .from('service_rates') .select('*') .order('service_type') if (dbError) { console.warn('从数据库加载费率失败,使用默认费率:', dbError.message) serviceRates.value = [...defaultRates.value] } else { serviceRates.value = data || [...defaultRates.value] } } catch (err) { console.warn('费率加载错误,使用默认费率:', err) serviceRates.value = [...defaultRates.value] error.value = '费率加载失败,使用默认配置' } finally { loading.value = false } } // 保存费率配置到数据库 const saveRates = async (rates: ServiceRate[]) => { loading.value = true error.value = null try { // 先删除现有费率 await supabase.from('service_rates').delete().neq('id', '') // 插入新费率 const { data, error: dbError } = await supabase .from('service_rates') .insert(rates.map(rate => ({ ...rate, updated_at: new Date().toISOString() }))) if (dbError) throw dbError serviceRates.value = [...rates] return { success: true, data } } catch (err) { console.error('保存费率失败:', err) error.value = '保存费率失败' return { success: false, error: err } } finally { loading.value = false } } // 获取指定服务类型的费率 const getRateByServiceType = (serviceType: string): ServiceRate | null => { return serviceRates.value.find(rate => rate.service_type === serviceType) || null } // 计算订单费用 const calculateOrderCost = ( serviceType: string, sourceLanguage: string, targetLanguage: string, urgency: 'normal' | 'urgent' | 'very_urgent' = 'normal', estimatedDuration?: number, // 分钟 estimatedWords?: number, // 字数 estimatedPages?: number // 页数 ): CostCalculation => { const rate = getRateByServiceType(serviceType) if (!rate) { throw new Error(`未找到服务类型 ${serviceType} 的费率配置`) } // 基础价格 let baseCost = rate.base_price // 根据服务类型计算额外费用 if (rate.price_per_minute && estimatedDuration) { baseCost += rate.price_per_minute * estimatedDuration } if (rate.price_per_word && estimatedWords) { baseCost += rate.price_per_word * estimatedWords } if (rate.price_per_page && estimatedPages) { baseCost += rate.price_per_page * estimatedPages } // 紧急程度倍数 const urgencyMultiplier = rate.urgency_multiplier[urgency] || 1.0 // 语言对倍数 const languagePair = `${sourceLanguage}-${targetLanguage}` const languageMultiplier = rate.language_pair_multiplier[languagePair] || 1.0 // 计算最终费用 const urgencyFee = baseCost * (urgencyMultiplier - 1) const languageFee = baseCost * (languageMultiplier - 1) const totalCost = baseCost * urgencyMultiplier * languageMultiplier return { baseCost, urgencyMultiplier, languageMultiplier, totalCost: Math.round(totalCost * 100) / 100, // 保留两位小数 breakdown: { basePrice: baseCost, urgencyFee: Math.round(urgencyFee * 100) / 100, languageFee: Math.round(languageFee * 100) / 100, estimatedDuration, estimatedWords } } } // 获取服务类型选项 const serviceTypeOptions = computed(() => { return serviceRates.value.map(rate => ({ value: rate.service_type, label: rate.service_name, basePrice: rate.base_price })) }) // 获取所有语言对的费率倍数 const getLanguagePairMultipliers = (serviceType: string) => { const rate = getRateByServiceType(serviceType) return rate ? rate.language_pair_multiplier : {} } // 初始化费率配置 const initializeRates = async () => { await loadRates() // 如果数据库中没有费率配置,则保存默认配置 if (serviceRates.value.length === 0) { await saveRates(defaultRates.value) } } return { // 数据 serviceRates: readonly(serviceRates), loading: readonly(loading), error: readonly(error), // 计算属性 serviceTypeOptions, // 方法 loadRates, saveRates, getRateByServiceType, calculateOrderCost, getLanguagePairMultipliers, initializeRates } }