v4.0.18版本提交
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import ExcelJS from 'exceljs';
|
||||
import PDFDocument from 'pdfkit';
|
||||
import {
|
||||
FINANCE_BANK_ACCOUNT_TYPE_LABELS,
|
||||
type FinanceBankAccountDto,
|
||||
} from '@dukang/shared-types';
|
||||
import { pickExportColumns, type ExportColumnDef } from '../../common/export/column-export.util';
|
||||
|
||||
function resolvePdfFontPath(): string {
|
||||
const candidates = [
|
||||
process.env.EXPORT_PDF_FONT_PATH,
|
||||
path.join(process.cwd(), 'assets', 'fonts', 'NotoSansSC-Regular.otf'),
|
||||
path.join(process.cwd(), 'assets', 'fonts', 'simhei.ttf'),
|
||||
path.join(process.cwd(), 'assets', 'fonts', 'msyh.ttc'),
|
||||
path.join(process.cwd(), 'dist', 'assets', 'fonts', 'simhei.ttf'),
|
||||
'/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc',
|
||||
'/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
|
||||
'C:\\Windows\\Fonts\\simhei.ttf',
|
||||
'C:\\Windows\\Fonts\\msyh.ttc',
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (fs.existsSync(candidate)) return candidate;
|
||||
}
|
||||
throw new Error('未找到可用于 PDF 的中文字体,请将字体文件放到 server/dukang-api/assets/fonts/');
|
||||
}
|
||||
|
||||
function columnDefs(): ExportColumnDef<FinanceBankAccountDto>[] {
|
||||
return [
|
||||
{ key: 'type', header: '类型', value: (r) => FINANCE_BANK_ACCOUNT_TYPE_LABELS[r.type] },
|
||||
{ key: 'ownerName', header: '归属', value: (r) => r.ownerName },
|
||||
{ key: 'cityName', header: '城市', value: (r) => r.cityName ?? '' },
|
||||
{ key: 'bankAccountName', header: '户名', value: (r) => r.bankAccountName },
|
||||
{ key: 'bankAccountNo', header: '银行账号', value: (r) => r.bankAccountNo },
|
||||
{ key: 'bankBranch', header: '开户行', value: (r) => r.bankBranch ?? '' },
|
||||
{ key: 'isDefault', header: '默认', value: (r) => (r.type === 'STORE' ? (r.isDefault ? '是' : '否') : '') },
|
||||
{ key: 'remark', header: '备注', value: (r) => r.remark ?? '' },
|
||||
];
|
||||
}
|
||||
|
||||
export async function buildFinanceBankAccountsXlsx(rows: FinanceBankAccountDto[]): Promise<Buffer> {
|
||||
const cols = pickExportColumns(columnDefs());
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet('银行账户');
|
||||
sheet.addRow(cols.map((c) => c.header));
|
||||
for (const row of rows) {
|
||||
sheet.addRow(cols.map((c) => c.value(row)));
|
||||
}
|
||||
sheet.columns.forEach((col) => {
|
||||
col.width = 18;
|
||||
});
|
||||
const buffer = await workbook.xlsx.writeBuffer();
|
||||
return Buffer.from(buffer);
|
||||
}
|
||||
|
||||
export async function buildFinanceBankAccountsPdf(rows: FinanceBankAccountDto[]): Promise<Buffer> {
|
||||
const cols = pickExportColumns(columnDefs());
|
||||
const fontPath = resolvePdfFontPath();
|
||||
const chunks: Buffer[] = [];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const doc = new PDFDocument({ size: 'A4', layout: 'landscape', margin: 24, bufferPages: true });
|
||||
doc.on('data', (c) => chunks.push(c as Buffer));
|
||||
doc.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
doc.on('error', reject);
|
||||
doc.font(fontPath);
|
||||
doc.fontSize(12).text('银行账户');
|
||||
doc.moveDown(0.4);
|
||||
doc.fontSize(9).text(cols.map((c) => c.header).join(' | '));
|
||||
doc.moveDown(0.3);
|
||||
for (const row of rows) {
|
||||
doc.text(cols.map((c) => String(c.value(row))).join(' | '));
|
||||
}
|
||||
doc.end();
|
||||
});
|
||||
}
|
||||
|
||||
export function buildFinanceBankExportFilename(format: 'xlsx' | 'pdf', count: number): string {
|
||||
const stamp = new Date().toISOString().slice(0, 10);
|
||||
return `银行账户_${stamp}_${count}.${format}`;
|
||||
}
|
||||
Reference in New Issue
Block a user