import { File, Paths } from 'expo-file-system'; import * as Sharing from 'expo-sharing'; import type { LedgerRecord } from '../types'; import { findCategory } from '../constants'; // 导出 CSV(Excel 可直接打开)并分享 export async function exportCSV(records: LedgerRecord[]): Promise<{ success: boolean; error?: string }> { try { if (records.length === 0) { return { success: false, error: '暂无数据可导出' }; } const header = ['日期', '类型', '分类', '金额', '备注', '报销状态']; const lines = records.map((r) => { const cat = findCategory(r.category, r.type); const status = !r.reimbursable ? '-' : r.reimbursed ? '已报销' : '待报销'; return [ r.date, r.type === 'expense' ? '支出' : '收入', cat.label, // v0.11 修复:金额不带千分位逗号(此前 Excel 按文本处理无法求和) (r.type === 'expense' ? '-' : '') + r.amount.toFixed(2), r.note, status, ]; }); // CSV 转义 const escape = (v: string) => `"${v.replace(/"/g, '""')}"`; const csv = [header, ...lines].map((row) => row.map(escape).join(',')).join('\r\n'); // 加 BOM 便于 Excel 识别 UTF-8 const content = '\uFEFF' + csv; const fileName = `tapledger_${getDateStr()}.csv`; const file = new File(Paths.cache, fileName); file.create({ intermediates: true, overwrite: true }); file.write(content); if (await Sharing.isAvailableAsync()) { await Sharing.shareAsync(file.uri, { mimeType: 'text/csv', dialogTitle: '导出 CSV', UTI: 'public.comma-separated-values-text', }); return { success: true }; } return { success: false, error: '当前设备不支持分享' }; } catch { return { success: false, error: '导出失败,请重试' }; } } function getDateStr(): string { const now = new Date(); return `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`; }