首页/ mobileweb/ 小草记账本/ 代码预览

💻 代码预览 · 小草记账本

mw_tool · 上传者 小草网络
← 返回详情
xiaocao-accounting/app.js · 约 6069 字符
1// 小草记账本 · 交互逻辑
2
3// 首页
4function renderIndex(){
5  const totalIn=RECORDS.filter(r=>r.amount>0).reduce((s,r)=>s+r.amount,0)+8500;
6  const totalOut=Math.abs(RECORDS.filter(r=>r.amount<0).reduce((s,r)=>s+r.amount,0));
7  document.getElementById('ms-balance').textContent='¥'+(totalIn-totalOut).toLocaleString();
8  document.getElementById('ms-in').textContent='¥'+totalIn.toLocaleString();
9  document.getElementById('ms-out').textContent='¥'+totalOut.toLocaleString();
10  document.getElementById('recent-list').innerHTML=RECORDS.slice(0,5).map(r=>`
11    <div class="recent-item">
12      <div class="ri-icon" style="background:${r.color}">${r.icon}</div>
13      <div class="ri-info"><div class="ri-cat">${r.cat}</div><div class="ri-desc">${r.desc} · ${r.time}</div></div>
14      <div class="ri-amount ${r.amount>0?'inc':'exp'}">${r.amount>0?'+':'-'}¥${Math.abs(r.amount)}</div>
15    </div>`).join('');
16  document.getElementById('account-list').innerHTML=ACCOUNTS.map(a=>`
17    <div class="recent-item">
18      <div class="ri-icon" style="background:var(--primary-light)">${a.icon}</div>
19      <div class="ri-info"><div class="ri-cat">${a.name}</div></div>
20      <div class="ri-amount ${a.balance<0?'exp':'inc'}">${a.balance<0?'-':'+'}¥${Math.abs(a.balance).toLocaleString()}</div>
21    </div>`).join('');
22}
23
24// 记一笔
25let recType='out', recCat='', amountVal='', note='';
26function initRecord(){
27  recType=location.search.includes('t=in')?'in':'out';
28  switchTab(recType);
29}
30function switchTab(t){ recType=t;
31  document.getElementById('tab-out').classList.toggle('active',t==='out');
32  document.getElementById('tab-in').classList.toggle('active',t==='in');
33  renderCats();
34}
35function renderCats(){
36  const cats=recType==='out'?CATS_OUT:CATS_IN;
37  if(!recCat||!cats.find(c=>c.name===recCat)) recCat=cats[0].name;
38  document.getElementById('cat-grid').innerHTML=cats.map(c=>`
39    <div class="cat-item ${c.name===recCat?'active':''}" onclick="selectCat('${c.name}')">
40      <div class="ci-icon" style="background:${c.color}">${c.icon}</div>
41      <div class="ci-name">${c.name}</div>
42    </div>`).join('');
43}
44function selectCat(n){ recCat=n; renderCats(); }
45function press(k){
46  if(k==='⌫'){ amountVal=amountVal.slice(0,-1); }
47  else if(k==='.'){ if(!amountVal.includes('.')) amountVal+=amountVal?'.':'0.'; }
48  else { if(amountVal.includes('.')&&amountVal.split('.')[1].length>=2) return; if(amountVal==='0') amountVal=k; else amountVal+=k; }
49  document.getElementById('amount-val').textContent=(parseFloat(amountVal||0)).toFixed(2);
50}
51function saveRecord(){
52  if(!amountVal||parseFloat(amountVal)<=0){ alert('请输入金额'); return; }
53  alert('✅ 记账成功!\n\n'+(recType==='out'?'支出':'收入')+' ¥'+parseFloat(amountVal).toFixed(2)+'\n分类:'+recCat+(note?'\n备注:'+note:''));
54  location.href='index.html';
55}
56
57// 统计
58function renderStats(){
59  const totalIn=RECORDS.filter(r=>r.amount>0).reduce((s,r)=>s+r.amount,0)+8500;
60  const totalOut=Math.abs(RECORDS.filter(r=>r.amount<0).reduce((s,r)=>s+r.amount,0));
61  document.getElementById('s-in').textContent='¥'+totalIn.toLocaleString();
62  document.getElementById('s-out').textContent='¥'+totalOut.toLocaleString();
63  document.getElementById('s-avg').textContent='¥'+Math.round(totalOut/11);
64  document.getElementById('s-budget').textContent='¥'+(7300-totalOut).toLocaleString();
65  const max=Math.max(...WEEK.map(w=>w.amt));
66  document.getElementById('week-chart').innerHTML=WEEK.map(w=>`
67    <div class="bar ${w.active?'active':''}" style="height:${w.amt/max*90+4}px">
68      <div class="bar-val">${w.amt}</div>
69      <div class="bar-label">周${w.day}</div>
70    </div>`).join('');
71  const pieData=[
72    {name:'餐饮',amt:1280,color:'#faad14'},{name:'购物',amt:980,color:'#ff4d4f'},
73    {name:'居家',amt:1200,color:'#52c41a'},{name:'交通',amt:286,color:'#13c2c2'},
74    {name:'娱乐',amt:468,color:'#722ed1'},{name:'其他',amt:1469,color:'#999'},
75  ];
76  const total=pieData.reduce((s,p)=>s+p.amt,0);
77  document.getElementById('pie-legend').innerHTML=pieData.map(p=>`
78    <div class="pl-row">
79      <span class="pl-dot" style="background:${p.color}"></span>
80      <span class="pl-name">${p.name}</span>
81      <span class="pl-pct">${Math.round(p.amt/total*100)}%</span>
82      <span class="pl-amt">¥${p.amt.toLocaleString()}</span>
83    </div>`).join('');
84}
85
86// 预算
87function renderBudget(){
88  document.getElementById('budget-list').innerHTML=BUDGETS.map(b=>{
89    const pct=Math.min(100,Math.round(b.used/b.limit*100));
90    const color=b.status==='ok'?'var(--green)':b.status==='warn'?'var(--accent)':'var(--red)';
91    const label=b.status==='ok'?'正常':b.status==='warn'?'警戒':'超支';
92    return `<div class="budget-item">
93      <div class="bi-top"><span class="bi-name">${b.name}</span><span class="bi-status ${b.status}">${label}</span></div>
94      <div class="bi-bar"><div class="bi-fill" style="width:${pct}%;background:${color}"></div></div>
95      <div class="bi-meta"><span>¥${b.used.toLocaleString()} / ¥${b.limit.toLocaleString()}</span><span style="color:${color};font-weight:600">${pct}%</span></div>
96    </div>`;
97  }).join('');
98}
99
100// 多账本
101function renderBooks(){
102  document.getElementById('book-grid').innerHTML=BOOKS.map((b,i)=>`
103    <div class="book-card ${b.active?'active':''}" onclick="switchBook(${i})">
104      <div class="bc-icon">${b.icon}</div>
105      <div class="bc-name">${b.name}${b.active?' · 当前':''}</div>
106      <div class="bc-desc">${b.desc}</div>
107      <div class="bc-balance">¥${b.balance.toLocaleString()}</div>
108    </div>`).join('');
109}
110function switchBook(i){
111  BOOKS.forEach((b,j)=>b.active=(i===j));
112  renderBooks();
113}
114
115// 我的
116function renderMine(){
117  document.getElementById('p-name').textContent=USER.name;
118  document.getElementById('p-days').textContent=USER.days;
119  document.getElementById('p-records').textContent=USER.records;
120  document.getElementById('p-budgets').textContent=USER.budgets;
121}
122