下载地址:https://www.pan38.com/share.php?code=93SjD 提取码:8888 【仅供学习用途】
声明:此篇文章仅用于学习用途使用,请勿用于违规用途,如果侵权请联系作者删除
本模拟器通过前端技术生成虚拟交易数据,用于学习以下技术:
<div class="bank-container">
<h2>虚拟流水生成器</h2>
<div class="controls">
<label>起始日期:<input type="date" id="startDate"></label>
<label>生成天数:<input type="number" id="days" min="1" max="365" value="30"></label>
<button id="generate">生成数据</button>
<button id="export">导出CSV</button>
</div>
<table id="statement">
<thead>
<tr>
<th>日期</th>
<th>交易类型</th>
<th>金额</th>
<th>余额</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>class BankStatementGenerator {
constructor() {
this.transactions = [];
this.balance = 10000; // 初始余额
}
generate(startDate, days) {
const types = ['工资','转账','消费','理财'];
for(let i=0; i<days; i++) {
const date = new Date(startDate);
date.setDate(date.getDate() + i);
const amount = this._randomAmount(types[Math.floor(Math.random()*4)]);
this.balance += amount;
this.transactions.push({
date: date.toLocaleDateString(),
type: amount > 0 ? '收入' : '支出',
amount: amount.toFixed(2),
balance: this.balance.toFixed(2)
});
}
return this.transactions;
}
_randomAmount(type) {
// 根据不同交易类型生成不同范围的金额
const ranges = {
'工资': [3000, 20000],
'转账': [-5000, 5000],
'消费': [-2000, -10],
'理财': [-10000, 3000]
};
const [min, max] = ranges[type];
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}
class BankStatementGenerator {
constructor(initialBalance = 10000) {
this.transactions = [];
this.balance = initialBalance;
this.categories = {
income: ['工资', '奖金', '理财收益', '转账收入'],
expense: ['餐饮', '购物', '房租', '交通', '娱乐']
};
}
generate(startDate, days, options = {}) {
const {
minAmount = 10,
maxAmount = 20000,
transactionChance = 0.7
} = options;
for(let i = 0; i < days; i++) {
const currentDate = new Date(startDate);
currentDate.setDate(currentDate.getDate() + i);
// 每天随机1-3笔交易
const transactionsPerDay = Math.floor(Math.random() * 3) + 1;
for(let j = 0; j < transactionsPerDay; j++) {
if(Math.random() > transactionChance) continue;
const isIncome = Math.random() > 0.6;
const type = this._getRandomType(isIncome);
const amount = this._calculateAmount(type, minAmount, maxAmount);
this._addTransaction({
date: currentDate,
type,
amount,
note: this._generateNote(type)
});
}
}
return this.transactions;
}
_getRandomType(isIncome) {
const pool = isIncome ?
this.categories.income :
this.categories.expense;
return pool[Math.floor(Math.random() * pool.length)];
}
_calculateAmount(type, min, max) {
let amount = 0;
switch(type) {
case '工资':
amount = Math.floor(Math.random() * (20000 - 8000 + 1)) + 8000;
break;
case '房租':
amount = -Math.floor(Math.random() * (6000 - 3000 + 1)) - 3000;
break;
default:
const base = Math.random() > 0.5 ?
Math.floor(Math.random() * (max - min + 1)) + min :
-(Math.floor(Math.random() * (max - min + 1)) + min);
amount = base;
}
return parseFloat(amount.toFixed(2));
}
_generateNote(type) {
const notes = {
'工资': `${new Date().getMonth()+1}月工资`,
'房租': `${new Date().getFullYear()}年房租`,
'餐饮': `${['午餐','晚餐','咖啡'][Math.floor(Math.random()*3)]}消费`
};
return notes[type] || type;
}
_addTransaction({date, type, amount, note}) {
this.balance += amount;
this.transactions.push({
date: date.toISOString().split('T')[0],
type,
amount: amount.toFixed(2),
balance: this.balance.toFixed(2),
note
});
}
exportToCSV(filename = 'statement') {
let csv = '日期,类型,金额,余额,备注\n';
this.transactions.forEach(t => {
csv += `${t.date},${t.type},${t.amount},${t.balance},${t.note}\n`;
});
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${filename}_${new Date().toISOString().slice(0,10)}.csv`;
a.click();
URL.revokeObjectURL(url);
}
}
// UI控制器
class StatementUI {
constructor() {
this.generator = new BankStatementGenerator();
this.initElements();
this.bindEvents();
}
initElements() {
this.elements = {
startDate: document.getElementById('startDate'),
days: document.getElementById('days'),
generateBtn: document.getElementById('generate'),
exportBtn: document.getElementById('export'),
tableBody: document.querySelector('#statement tbody')
};
}
bindEvents() {
this.elements.generateBtn.addEventListener('click', () => this.generateStatement());
this.elements.exportBtn.addEventListener('click', () => this.generator.exportToCSV());
}
generateStatement() {
const startDate = this.elements.startDate.value || new Date().toISOString().slice(0,10);
const days = parseInt(this.elements.days.value) || 30;
this.generator = new BankStatementGenerator();
const transactions = this.generator.generate(startDate, days);
this.renderTable(transactions);
}
renderTable(data) {
this.elements.tableBody.innerHTML = '';
data.forEach(t => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${t.date}</td>
<td>${t.type}</td>
<td class="${t.amount >= 0 ? 'income' : 'expense'}">
${t.amount}
</td>
<td>${t.balance}</td>
<td>${t.note}</td>
`;
this.elements.tableBody.appendChild(row);
});
}
}
// 初始化
document.addEventListener('DOMContentLoaded', () => {
new StatementUI();
});