// 向测试环境灌入演示数据:登录测试账号,解析并确认导入样例账单。 import { readFile } from 'node:fs/promises' import { basename, join, resolve } from 'node:path' import axios from 'axios' import { login } from './browser.js' import { API_URL, ROOT } from './config.js' /** 样例账单目录(doc-site 内的虚构样例,全部为虚假数据,禁止使用真实账单) */ const BILL_DIR = resolve(ROOT, 'scripts', 'samples') /** 待导入样例:账单类型、相对路径、解压密码(仅使用虚构数据) */ const SAMPLES: Array<[string, string, string | null]> = [ ['ALIPAY', 'alipay_fake.csv', null], ['TAOBAO', 'taobao_fake.xlsx', null], ['JD', 'jd_fake.csv', null], ] interface ParsedRow { externalNo: string transactionTime: string type: string amount: number counterparty?: string | null product?: string | null includeInStats?: boolean importable?: boolean rawData?: string | null } /** * 调用解析接口解析账单文件。 * * @param token 访问令牌 * @param billType 账单类型 * @param path 账单文件路径 * @param password 解压密码 * @returns 解析结果数据 */ async function parseBill(token: string, billType: string, path: string, password: string | null): Promise { const buf = await readFile(path) const form = new FormData() form.append('file', new Blob([buf]), basename(path)) form.append('billType', billType) if (password) form.append('password', password) const res = await axios.post(`${API_URL}/transaction/import/parse`, form, { headers: { Authorization: `Bearer ${token}` }, timeout: 120000, }) if (res.data.code !== 200) throw new Error(res.data.message) return res.data.data } /** * 确认导入解析出的账单行。 * * @param token 访问令牌 * @param billType 账单类型 * @param rows 解析结果行 * @returns 导入结果数据 */ async function confirmBill(token: string, billType: string, rows: ParsedRow[]): Promise { const items = rows .filter((r) => r.importable !== false) .map((r) => ({ externalNo: r.externalNo, transactionTime: r.transactionTime, type: r.type, amount: r.amount, counterparty: r.counterparty ?? null, product: r.product ?? null, includeInStats: r.includeInStats ?? true, rawData: r.rawData ?? null, })) const res = await axios.post( `${API_URL}/transaction/import/confirm`, { billType, items }, { headers: { Authorization: `Bearer ${token}` }, timeout: 120000 }, ) if (res.data.code !== 200) throw new Error(res.data.message) return res.data.data } async function main(): Promise { const token = await login() console.log('登录成功') for (const [billType, relPath, password] of SAMPLES) { const path = join(BILL_DIR, relPath) try { const data = await parseBill(token, billType, path, password) const rows: ParsedRow[] = data.rows ?? [] const importable = rows.filter((r) => r.importable !== false) console.log(`[解析成功] ${billType}: 共 ${rows.length} 行,可导入 ${importable.length} 行`) const result = await confirmBill(token, billType, rows) console.log(`[导入成功] ${billType}: ${JSON.stringify(result)}`) } catch (err) { console.log(`[失败] ${billType}: ${err}`) } } } main().catch((err) => { console.error('FAIL', err) process.exit(1) })