HTML5消费收入矩阵计算器
由于这是一个复杂的计算器,我们将分步骤构建:
-
设计输入部分:消费项目、收入项目、生活成本(可以视为一种固定消费)
-
每个项目包括:名称、金额(分)、周期(天、周、月、年)
-
计算覆盖200年,我们需要一个时间范围选择(起始年份和结束年份,或者固定200年,从当前年开始)
-
计算矩阵:将每个消费和收入按周期转换为每年的总金额,然后按年汇总,并计算每年的结余。
考虑到200年数据量较大,我们不会在页面上展示全部200年的矩阵,而是提供汇总和按年查看的功能。
我们将使用以下步骤:
-
输入部分:使用表格动态添加行(消费和收入分开)
-
周期转换:将不同周期的金额转换为年金额(按一年365天,一周7天,一月30天,一年12个月,一年1年计算)
-
计算生活成本:生活成本可以视为每年固定支出,也可以设置为周期性(这里我们将其视为每年固定,但也可以设计为周期性,为了通用性,我们将生活成本也设计为周期性支出,但通常按年计算)
注意:由于周期转换存在小数,我们使用浮点数计算,但最终金额以分单位,所以要注意精度。
由于项目要求精确到分,我们使用分作为单位,但在输入时可以使用元,然后转换为分(1元=100分),或者直接输入分。这里为了用户方便,我们使用元作为输入,然后转换为分。
步骤:
-
创建HTML结构,包括消费项目表、收入项目表、生活成本表(可以单独一行,也可以作为消费项目的一种,但为了突出,我们单独设置)
-
为每个表提供添加行的按钮,以及删除行的功能。
-
提供计算按钮,计算从起始年份到结束年份(共200年)的每年消费、收入、生活成本及结余。
-
展示结果:可以选择展示每年数据,或者只展示汇总数据(如总消费、总收入、总生活成本、总结余等)
由于200年数据太多,我们默认展示汇总数据,并提供按年份查看的表格(可滚动)。
我们假设起始年份为当前年份,结束年份为当前年份+199(共200年)。
周期转换公式:
天:年金额 = 金额 * (365 / 周期天数) 注意:周期为天,比如每3天,那么周期天数为3,则一年有365/3次
周:年金额 = 金额 * (52 / 周期周数) 一年52周
月:年金额 = 金额 * (12 / 周期月数)
年:年金额 = 金额 / 周期年数
但是注意:我们这里周期是指每多少天/周/月/年一次。例如,每3天一次,那么周期类型为天,周期数为3。
因此,我们定义转换函数:
周期类型为天:年次数 = 365 / 周期数
周期类型为周:年次数 = 52 / 周期数
周期类型为月:年次数 = 12 / 周期数
周期类型为年:年次数 = 1 / 周期数
然后年金额 = 单次金额 * 年次数
注意:生活成本也可以按照同样的方式计算,但通常生活成本是按年计算的,我们可以单独设置一个生活成本,也可以作为消费项目。
为了简化,我们将生活成本视为一个每年固定的消费项目,并且不允许改变周期(按年)。但为了通用,我们也可以让生活成本设置周期。
我们这样设计:
消费项目:包括日常消费,可以有任意周期。
收入项目:同样任意周期。
生活成本:我们单独列出来,作为每年固定支出,但也可以设置为周期性,这里我们将其视为一个按年周期的消费项目,但单独输入。
因此,我们将在输入部分单独设置生活成本,其周期固定为年,周期数为1。
但是,为了灵活性,我们也可以让生活成本设置周期。所以,我们将生活成本视为一个特殊的消费项目,并单独输入。
实际上,我们可以将生活成本合并到消费项目中,但为了突出,我们单独列出。
我们决定:生活成本输入框,只输入金额(年金额),因为生活成本通常按年计算。这样,生活成本就是每年固定金额。
计算步骤:
-
将消费项目的每个项目按周期转换为年金额(分)
-
将收入项目的每个项目按周期转换为年金额(分)
-
生活成本直接作为年金额(分)
-
对于每一年,计算该年的总消费(所有消费项目年金额之和 + 生活成本),总收入(所有收入项目年金额之和),然后结余 = 总收入 - 总消费。
注意:每个消费/收入项目可能只在一定年份内有效,但这里我们没有设置项目的开始和结束年份,所以默认在整个200年内都有效。
如果要求更复杂,比如项目有开始和结束年份,那么我们需要在输入时增加开始年份和结束年份。但题目没有要求,我们暂不考虑。
因此,我们假设每个消费和收入项目在整个200年内都按照固定周期发生。
开始编码:
结构:
-
消费项目表:名称、金额(元)、周期类型(天、周、月、年)、周期数、操作(删除)
-
收入项目表:同上
-
生活成本:输入框(元)
-
计算按钮
-
结果区域:汇总和按年查看
注意:金额输入为元,但计算时转换为分(乘以100),以避免浮点数精度问题。但注意,在计算过程中,由于周期转换可能有小数,我们仍然使用浮点数,最后四舍五入到分。
但是,由于周期转换后年金额可能是小数,我们按分四舍五入到整数(因为最小单位是分,不能有更小的单位)。
步骤:
-
创建消费和收入表格,可以动态添加行。
-
为每个表格实现添加行和删除行的功能。
-
计算时,遍历每个消费项目,根据周期类型和周期数计算年金额(分),然后累加得到每年总消费。
-
同样计算收入。
-
生活成本直接乘以100(转换为分)作为每年生活成本。
-
然后计算每年的结余。
由于200年数据量很大,我们只展示前几年和最后几年,中间用省略号表示,或者使用可滚动的表格。
我们选择使用可滚动的表格展示全部200年数据。
代码结构:
HTML部分:
<h1>消费、收入和生活成本矩阵计算器(200年)</h1>
<div>
<h2>消费项目</h2>
<table id="expenseTable">
<thead>
<tr>
<th>名称</th>
<th>金额(元)</th>
<th>周期类型</th>
<th>周期数</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- 动态添加行 -->
</tbody>
</table>
<button onclick="addExpenseRow()">添加消费项目</button>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>消费与收入矩阵计算器</title>
<style>
:root {
--primary-color: #4a6fa5;
--secondary-color: #6b8cbc;
--accent-color: #ff6b6b;
--light-color: #f8f9fa;
--dark-color: #343a40;
--success-color: #28a745;
--border-radius: 8px;
--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f5f7fa;
color: var(--dark-color);
line-height: 1.6;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
padding: 30px;
}
header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eaeaea;
}
h1 {
color: var(--primary-color);
margin-bottom: 10px;
}
.description {
color: #6c757d;
font-size: 1.1rem;
max-width: 800px;
margin: 0 auto;
}
.input-section {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
margin-bottom: 30px;
}
@media (max-width: 768px) {
.input-section {
grid-template-columns: 1fr;
}
}
.card {
background-color: var(--light-color);
border-radius: var(--border-radius);
padding: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.card h2 {
color: var(--primary-color);
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #dee2e6;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 500;
}
input, select {
width: 100%;
padding: 10px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 1rem;
}
button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
}
button:hover {
background-color: var(--secondary-color);
}
.btn-danger {
background-color: var(--accent-color);
}
.btn-danger:hover {
background-color: #ff5252;
}
.btn-success {
background-color: var(--success-color);
}
.btn-success:hover {
background-color: #218838;
}
.items-list {
max-height: 400px;
overflow-y: auto;
margin-top: 20px;
}
.item-row {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
gap: 10px;
padding: 10px;
border-bottom: 1px solid #eaeaea;
align-items: center;
}
.item-row.header {
font-weight: bold;
background-color: #e9ecef;
position: sticky;
top: 0;
}
.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}