const Excel = require('exceljs'); // 配置 const OUTPUT_FILE = 'purchase_test_data_2000_v2.xlsx'; const RECORD_COUNT = 2000; // 数据池 const PURCHASE_CATEGORIES = ['货物类', '工程类', '服务类', '软件系统', '办公设备', '家具用具', '专用设备', '通讯设备']; const PURCHASE_METHODS = ['公开招标', '邀请招标', '询价采购', '单一来源', '竞争性谈判']; const DEPARTMENTS = ['人事部', '行政部', '财务部', '技术部', '市场部', '采购部', '研发部']; const EMPLOYEES = [ { id: 'EMP0001', name: '张伟' }, { id: 'EMP0002', name: '王芳' }, { id: 'EMP0003', name: '李娜' }, { id: 'EMP0004', name: '刘洋' }, { id: 'EMP0005', name: '陈静' }, { id: 'EMP0006', name: '杨强' }, { id: 'EMP0007', name: '赵敏' }, { id: 'EMP0008', name: '孙杰' }, { id: 'EMP0009', name: '周涛' }, { id: 'EMP0010', name: '吴刚' }, { id: 'EMP0011', name: '郑丽' }, { id: 'EMP0012', name: '钱勇' }, { id: 'EMP0013', name: '何静' }, { id: 'EMP0014', name: '朱涛' }, { id: 'EMP0015', name: '马超' } ]; // 生成随机整数 function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } // 生成随机浮点数 function randomFloat(min, max, decimals = 2) { const num = Math.random() * (max - min) + min; return parseFloat(num.toFixed(decimals)); } // 从数组中随机选择 function randomChoice(arr) { return arr[Math.floor(Math.random() * arr.length)]; } // 生成随机日期 function randomDate(start, end) { return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); } // 生成采购事项ID function generatePurchaseId(index) { const timestamp = Date.now(); const num = String(index + 1).padStart(4, '0'); return `PUR${timestamp}${num}`; } // 生成测试数据 function generateTestData(count) { const data = []; const startDate = new Date('2023-01-01'); const endDate = new Date('2025-12-31'); for (let i = 0; i < count; i++) { const purchaseQty = randomFloat(1, 5000, 2); const unitPrice = randomFloat(100, 50000, 2); const budgetAmount = parseFloat((purchaseQty * unitPrice).toFixed(2)); const discount = randomFloat(0.85, 0.98, 2); const actualAmount = parseFloat((budgetAmount * discount).toFixed(2)); const employee = randomChoice(EMPLOYEES); // 生成Date对象 const applyDateObj = randomDate(startDate, endDate); // 生成后续日期(都比申请日期晚) const planApproveDate = new Date(applyDateObj); planApproveDate.setDate(planApproveDate.getDate() + randomInt(1, 7)); const announceDate = new Date(planApproveDate); announceDate.setDate(announceDate.getDate() + randomInt(3, 15)); const bidOpenDate = new Date(announceDate); bidOpenDate.setDate(bidOpenDate.getDate() + randomInt(5, 20)); const contractSignDate = new Date(bidOpenDate); contractSignDate.setDate(contractSignDate.getDate() + randomInt(3, 10)); const expectedDeliveryDate = new Date(contractSignDate); expectedDeliveryDate.setDate(expectedDeliveryDate.getDate() + randomInt(15, 60)); const actualDeliveryDate = new Date(expectedDeliveryDate); actualDeliveryDate.setDate(actualDeliveryDate.getDate() + randomInt(-2, 5)); const acceptanceDate = new Date(actualDeliveryDate); acceptanceDate.setDate(acceptanceDate.getDate() + randomInt(1, 7)); const settlementDate = new Date(acceptanceDate); settlementDate.setDate(settlementDate.getDate() + randomInt(7, 30)); data.push({ purchaseId: generatePurchaseId(i), purchaseCategory: randomChoice(PURCHASE_CATEGORIES), projectName: `${randomChoice(PURCHASE_CATEGORIES)}采购项目-${String(i + 1).padStart(4, '0')}`, subjectName: `${randomChoice(PURCHASE_CATEGORIES).replace('类', '')}配件-${String(i + 1).padStart(4, '0')}`, subjectDesc: `${randomChoice(PURCHASE_CATEGORIES)}采购项目标的物详细描述-${String(i + 1).padStart(4, '0')}`, purchaseQty: purchaseQty, budgetAmount: budgetAmount, bidAmount: actualAmount, actualAmount: actualAmount, contractAmount: actualAmount, settlementAmount: actualAmount, purchaseMethod: randomChoice(PURCHASE_METHODS), supplierName: `供应商公司-${String(i + 1).padStart(4, '0')}有限公司`, contactPerson: `联系人-${String(i + 1).padStart(4, '0')}`, contactPhone: `13${randomInt(0, 9)}${String(randomInt(10000000, 99999999))}`, supplierUscc: `91${randomInt(10000000, 99999999)}MA${String(randomInt(1000, 9999))}`, supplierBankAccount: `6222${String(randomInt(100000000000000, 999999999999999))}`, applyDate: applyDateObj, // Date对象 planApproveDate: planApproveDate, announceDate: announceDate, bidOpenDate: bidOpenDate, contractSignDate: contractSignDate, expectedDeliveryDate: expectedDeliveryDate, actualDeliveryDate: actualDeliveryDate, acceptanceDate: acceptanceDate, settlementDate: settlementDate, applicantId: employee.id, applicantName: employee.name, applyDepartment: randomChoice(DEPARTMENTS), purchaseLeaderId: randomChoice(EMPLOYEES).id, purchaseLeaderName: randomChoice(EMPLOYEES).name, purchaseDepartment: '采购部' }); } return data; } // 创建Excel文件 async function createExcelFile() { console.log('开始生成测试数据...'); console.log(`记录数: ${RECORD_COUNT}`); // 生成测试数据 const testData = generateTestData(RECORD_COUNT); console.log('测试数据生成完成'); // 创建工作簿 const workbook = new Excel.Workbook(); const worksheet = workbook.addWorksheet('采购交易数据'); // 定义列(按照Excel实体类的index顺序) worksheet.columns = [ { header: '采购事项ID', key: 'purchaseId', width: 25 }, { header: '采购类别', key: 'purchaseCategory', width: 15 }, { header: '项目名称', key: 'projectName', width: 30 }, { header: '标的物名称', key: 'subjectName', width: 30 }, { header: '标的物描述', key: 'subjectDesc', width: 35 }, { header: '采购数量', key: 'purchaseQty', width: 15 }, { header: '预算金额', key: 'budgetAmount', width: 18 }, { header: '中标金额', key: 'bidAmount', width: 18 }, { header: '实际采购金额', key: 'actualAmount', width: 18 }, { header: '合同金额', key: 'contractAmount', width: 18 }, { header: '结算金额', key: 'settlementAmount', width: 18 }, { header: '采购方式', key: 'purchaseMethod', width: 15 }, { header: '中标供应商名称', key: 'supplierName', width: 30 }, { header: '供应商联系人', key: 'contactPerson', width: 15 }, { header: '供应商联系电话', key: 'contactPhone', width: 18 }, { header: '供应商统一信用代码', key: 'supplierUscc', width: 25 }, { header: '供应商银行账户', key: 'supplierBankAccount', width: 25 }, { header: '采购申请日期', key: 'applyDate', width: 18 }, { header: '采购计划批准日期', key: 'planApproveDate', width: 18 }, { header: '采购公告发布日期', key: 'announceDate', width: 18 }, { header: '开标日期', key: 'bidOpenDate', width: 18 }, { header: '合同签订日期', key: 'contractSignDate', width: 18 }, { header: '预计交货日期', key: 'expectedDeliveryDate', width: 18 }, { header: '实际交货日期', key: 'actualDeliveryDate', width: 18 }, { header: '验收日期', key: 'acceptanceDate', width: 18 }, { header: '结算日期', key: 'settlementDate', width: 18 }, { header: '申请人工号', key: 'applicantId', width: 15 }, { header: '申请人姓名', key: 'applicantName', width: 15 }, { header: '申请部门', key: 'applyDepartment', width: 18 }, { header: '采购负责人工号', key: 'purchaseLeaderId', width: 15 }, { header: '采购负责人姓名', key: 'purchaseLeaderName', width: 15 }, { header: '采购部门', key: 'purchaseDepartment', width: 18 } ]; // 添加数据 worksheet.addRows(testData); // 设置表头样式 const headerRow = worksheet.getRow(1); headerRow.font = { bold: true }; headerRow.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE6E6FA' } }; // 保存文件 console.log('正在写入Excel文件...'); await workbook.xlsx.writeFile(OUTPUT_FILE); console.log(`✓ 文件已保存: ${OUTPUT_FILE}`); // 显示统计信息 console.log('\n========================================'); console.log('数据统计'); console.log('========================================'); console.log(`总记录数: ${testData.length}`); console.log(`采购数量范围: ${Math.min(...testData.map(d => d.purchaseQty))} - ${Math.max(...testData.map(d => d.purchaseQty))}`); console.log(`预算金额范围: ${Math.min(...testData.map(d => d.budgetAmount))} - ${Math.max(...testData.map(d => d.budgetAmount))}`); console.log('\n前3条记录预览:'); testData.slice(0, 3).forEach((record, index) => { console.log(`\n记录 ${index + 1}:`); console.log(` 采购事项ID: ${record.purchaseId}`); console.log(` 项目名称: ${record.projectName}`); console.log(` 采购数量: ${record.purchaseQty}`); console.log(` 预算金额: ${record.budgetAmount}`); console.log(` 申请人: ${record.applicantName} (${record.applicantId})`); console.log(` 申请部门: ${record.applyDepartment}`); console.log(` 申请日期: ${record.applyDate}`); }); } // 运行 createExcelFile().catch(console.error);