import { Injectable } from '@angular/core'; import { completionJSON } from 'fmode-ng/core/agent/chat/completion'; /** * 支付凭证AI分析服务 * 使用AI识别支付凭证图片中的金额、时间、支付方式等信息 */ @Injectable({ providedIn: 'root' }) export class PaymentVoucherAIService { constructor() {} /** * 分析支付凭证图片 * @param imageUrl 图片URL * @param onProgress 进度回调 * @returns 分析结果 */ async analyzeVoucher(options: { imageUrl: string; onProgress?: (progress: string) => void; }): Promise<{ amount: number; paymentMethod: string; paymentTime?: Date; transactionId?: string; payer?: string; receiver?: string; confidence: number; rawText?: string; }> { try { options.onProgress?.('正在识别支付凭证...'); // 构建AI识别提示词 const prompt = `请识别这张支付凭证图片中的信息,并按以下JSON格式输出: { "amount": 支付金额(数字), "paymentMethod": "支付方式(bank_transfer/alipay/wechat/cash/other)", "paymentTime": "支付时间(YYYY-MM-DD HH:mm:ss格式,如无法识别则为null)", "transactionId": "交易流水号或订单号", "payer": "付款人姓名或账号", "receiver": "收款人姓名或账号", "confidence": 识别置信度(0-1的小数), "rawText": "图片中的原始文字内容" } 要求: 1. 准确识别金额,包括小数点 2. 正确判断支付方式(如支付宝、微信、银行转账等) 3. 提取交易时间(年月日时分秒) 4. 提取交易流水号/订单号 5. 识别付款人和收款人信息 6. 评估识别的置信度 7. 保留原始文字内容作为参考 支付方式识别规则: - 看到"支付宝"、"Alipay" → alipay - 看到"微信"、"WeChat" → wechat - 看到"银行"、"转账"、"Bank" → bank_transfer - 看到"现金"、"Cash" → cash - 其他情况 → other`; const outputSchema = `{ "amount": 0, "paymentMethod": "bank_transfer", "paymentTime": null, "transactionId": "", "payer": "", "receiver": "", "confidence": 0.95, "rawText": "" }`; options.onProgress?.('AI正在分析凭证内容...'); // 使用fmode-ng的completionJSON进行视觉识别 const result = await completionJSON( prompt, outputSchema, (content) => { options.onProgress?.(`正在分析... ${Math.min(Math.round((content?.length || 0) / 10), 100)}%`); }, 2, // 最大重试次数 { // 使用豆包1.6视觉模型(与教辅名师项目一致) model: 'doubao-1.6', vision: true, images: [options.imageUrl] } ); console.log('✅ 支付凭证AI分析完成:', result); // 转换支付时间 let paymentTime: Date | undefined; if (result.paymentTime) { try { paymentTime = new Date(result.paymentTime); } catch (e) { console.warn('支付时间解析失败:', result.paymentTime); } } return { amount: parseFloat(result.amount) || 0, paymentMethod: result.paymentMethod || 'other', paymentTime, transactionId: result.transactionId || '', payer: result.payer || '', receiver: result.receiver || '', confidence: result.confidence || 0.8, rawText: result.rawText || '' }; } catch (error) { console.error('❌ 支付凭证AI分析失败:', error); // 返回默认值,表示分析失败 return { amount: 0, paymentMethod: 'other', confidence: 0, rawText: '分析失败: ' + (error.message || '未知错误') }; } } /** * 批量分析多张支付凭证 * @param imageUrls 图片URL数组 * @param onProgress 进度回调 * @returns 分析结果数组 */ async analyzeBatchVouchers(options: { imageUrls: string[]; onProgress?: (progress: string, index: number, total: number) => void; }): Promise>; }>> { const results: Array<{ imageUrl: string; result: Awaited>; }> = []; for (let i = 0; i < options.imageUrls.length; i++) { const imageUrl = options.imageUrls[i]; options.onProgress?.( `正在分析第 ${i + 1} / ${options.imageUrls.length} 张凭证...`, i + 1, options.imageUrls.length ); const result = await this.analyzeVoucher({ imageUrl, onProgress: (progress) => { options.onProgress?.( `第 ${i + 1} / ${options.imageUrls.length} 张:${progress}`, i + 1, options.imageUrls.length ); } }); results.push({ imageUrl, result }); } return results; } /** * 验证分析结果的合理性 * @param result 分析结果 * @returns 是否合理 */ validateResult(result: Awaited>): { valid: boolean; errors: string[]; } { const errors: string[] = []; // 检查金额 if (result.amount <= 0) { errors.push('金额必须大于0'); } if (result.amount > 10000000) { errors.push('金额超出合理范围(>1000万)'); } // 检查置信度 if (result.confidence < 0.5) { errors.push('识别置信度过低,建议人工核对'); } // 检查支付方式 const validMethods = ['bank_transfer', 'alipay', 'wechat', 'cash', 'other']; if (!validMethods.includes(result.paymentMethod)) { errors.push('支付方式无效'); } // 检查支付时间 if (result.paymentTime) { const now = new Date(); const oneYearAgo = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate()); const oneMonthLater = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate()); if (result.paymentTime < oneYearAgo) { errors.push('支付时间过早(超过1年前)'); } if (result.paymentTime > oneMonthLater) { errors.push('支付时间为未来时间'); } } return { valid: errors.length === 0, errors }; } /** * 格式化支付方式显示文本 * @param method 支付方式 * @returns 显示文本 */ formatPaymentMethod(method: string): string { const methodMap: Record = { 'bank_transfer': '银行转账', 'alipay': '支付宝', 'wechat': '微信支付', 'cash': '现金', 'other': '其他' }; return methodMap[method] || method; } /** * 获取置信度等级描述 * @param confidence 置信度 * @returns 等级描述 */ getConfidenceLevel(confidence: number): { level: 'high' | 'medium' | 'low'; text: string; color: string; } { if (confidence >= 0.8) { return { level: 'high', text: '高置信度', color: '#34c759' }; } else if (confidence >= 0.5) { return { level: 'medium', text: '中等置信度', color: '#ff9500' }; } else { return { level: 'low', text: '低置信度', color: '#ff3b30' }; } } }