根据提供的统计摘要,我看到有3个文件发生了变化:

- 新增了一个关于汇率预测的markdown文件(125行新增)
- 修改了一个工作计划汇报的HTML文件(大量修改)
- 新增了一个统计计算器的HTML文件(451行新增)

基于这些变化,生成的常规提交信息如下:

feat: 新增汇率预测文档和统计计算器功能

- 新增汇率预测相关的markdown文档
- 新增统计计算器HTML页面,提供数据分析功能
- 重构工作计划汇报页面,优化内容结构和布局
This commit is contained in:
史悦
2025-09-16 15:51:00 +08:00
parent 5c9a60ee27
commit 0d7d5b0a43
3 changed files with 955 additions and 411 deletions

View File

@@ -0,0 +1,451 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>回报率预测计算器</title>
<style>
:root {
color-scheme: light dark;
font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
background-color: #f7f8fa;
color: #1f2933;
}
body {
margin: 0;
padding: 32px;
display: flex;
justify-content: center;
}
.container {
width: min(1080px, 100%);
background: #ffffffee;
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
border-radius: 18px;
padding: 32px 36px 48px;
}
h1 {
margin: 0 0 8px;
font-size: 28px;
}
.subtitle {
margin: 0;
color: #52606d;
font-size: 16px;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin: 32px 0;
}
.summary-card {
border-radius: 14px;
padding: 20px 24px;
background: linear-gradient(135deg, #2563eb, #38bdf8);
color: #f8fafc;
}
.summary-card h2 {
font-size: 14px;
letter-spacing: 0.08em;
text-transform: uppercase;
margin: 0 0 12px;
}
.summary-value {
font-size: 28px;
font-weight: 700;
}
.input-section {
margin-bottom: 36px;
}
.input-section h3 {
margin: 0 0 16px;
font-size: 20px;
}
.field-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 18px;
}
label {
display: flex;
flex-direction: column;
gap: 6px;
font-size: 14px;
color: #364152;
}
input[type="number"] {
padding: 10px 14px;
border: 1px solid #d9e2ec;
border-radius: 10px;
font-size: 16px;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
input[type="number"]:focus {
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
outline: none;
}
.result-section {
margin-top: 40px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 24px;
}
th,
td {
padding: 12px 16px;
border-bottom: 1px solid #e4ebf3;
text-align: right;
}
th:first-child,
td:first-child {
text-align: left;
}
th {
background: #f0f4ff;
font-weight: 600;
}
.note {
font-size: 13px;
color: #e4ebf3;
}
@media (max-width: 768px) {
body {
padding: 16px;
}
.container {
padding: 24px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>回报率预测计算器</h1>
<p class="subtitle">根据《回报率预测》文档的假设提供默认值,可随场景调整实时查看财务指标。</p>
</header>
<div class="card-grid">
<div class="summary-card">
<h2>月度净利润</h2>
<div id="monthlyNetProfit" class="summary-value">¥ 33.00</div>
<p class="note">= 月毛利 - 固定运营成本</p>
</div>
<div class="summary-card">
<h2>投资回收期</h2>
<div id="paybackPeriod" class="summary-value">54.5 个月</div>
<p class="note">= 单站总投资 / 月净利润</p>
</div>
<div class="summary-card">
<h2>年化 ROI</h2>
<div id="annualROI" class="summary-value">22.0%</div>
<p class="note">= (年净利润 / 总投资) × 100%</p>
</div>
</div>
<section class="input-section">
<h3>核心量化假设</h3>
<div class="field-grid">
<label>
日均废纸板回收量 (公斤)
<input id="dailyCardboard" type="number" min="0" step="0.1" value="20" />
</label>
<label>
日均塑料瓶回收量 (公斤)
<input id="dailyPet" type="number" min="0" step="0.1" value="10" />
</label>
<label>
月计费天数 (天)
<input id="daysPerMonth" type="number" min="1" step="1" value="30" />
</label>
<label>
废纸板回收价 ¥/公斤 (给用户)
<input id="buyPriceCardboard" type="number" min="0" step="0.01" value="0.8" />
</label>
<label>
废纸板出售价 ¥/公斤 (给打包站)
<input id="sellPriceCardboard" type="number" min="0" step="0.01" value="1.2" />
</label>
<label>
塑料瓶回收价 ¥/公斤 (给用户)
<input id="buyPricePet" type="number" min="0" step="0.01" value="1.4" />
</label>
<label>
塑料瓶出售价 ¥/公斤 (给打包站)
<input id="sellPricePet" type="number" min="0" step="0.01" value="2.0" />
</label>
</div>
</section>
<section class="input-section">
<h3>运营及投入假设</h3>
<div class="field-grid">
<label>
场地合作分成 (占给站长回收金 %)
<input id="siteFeePercent" type="number" min="0" step="0.1" value="10" />
</label>
<label>
月物流清运成本 (¥)
<input id="logisticsCost" type="number" min="0" step="1" value="220" />
</label>
<label>
设备维护与网络费 (¥/月)
<input id="maintenanceCost" type="number" min="0" step="1" value="27" />
</label>
<label>
其他运营成本 (¥/月)
<input id="otherCost" type="number" min="0" step="1" value="50" />
</label>
<label>
单站设备投入 (¥)
<input id="equipmentCost" type="number" min="0" step="10" value="1500" />
</label>
<label>
部署及安装成本 (¥)
<input id="deploymentCost" type="number" min="0" step="10" value="300" />
</label>
</div>
</section>
<section class="result-section">
<h3>产出指标</h3>
<table>
<thead>
<tr>
<th>指标</th>
<th>废纸板</th>
<th>塑料瓶</th>
<th>合计</th>
</tr>
</thead>
<tbody>
<tr>
<td>月度回收量 (公斤)</td>
<td id="monthlyCardboardKg">600.0</td>
<td id="monthlyPetKg">300.0</td>
<td id="monthlyTotalKg">900.0</td>
</tr>
<tr>
<td>给用户回收金 (¥)</td>
<td id="payoutCardboard">¥ 480.00</td>
<td id="payoutPet">¥ 420.00</td>
<td id="payoutTotal">¥ 900.00</td>
</tr>
<tr>
<td>销售收入 (¥)</td>
<td id="saleCardboard">¥ 720.00</td>
<td id="salePet">¥ 600.00</td>
<td id="saleTotal">¥ 1,320.00</td>
</tr>
<tr>
<td>毛利 (¥)</td>
<td id="grossCardboard">¥ 240.00</td>
<td id="grossPet">¥ 180.00</td>
<td id="grossTotal">¥ 420.00</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>成本拆解</th>
<th>金额 (¥)</th>
</tr>
</thead>
<tbody>
<tr>
<td>场地合作费</td>
<td id="siteFee">¥ 90.00</td>
</tr>
<tr>
<td>月物流清运成本</td>
<td id="logisticsCostCell">¥ 220.00</td>
</tr>
<tr>
<td>设备维护与网络费</td>
<td id="maintenanceCostCell">¥ 27.00</td>
</tr>
<tr>
<td>其他运营成本</td>
<td id="otherCostCell">¥ 50.00</td>
</tr>
<tr>
<td><strong>固定成本合计</strong></td>
<td id="fixedCostTotal"><strong>¥ 387.00</strong></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>投资与回报</th>
<th>金额 / 指标</th>
</tr>
</thead>
<tbody>
<tr>
<td>单站总投资 (Capex)</td>
<td id="totalInvestment">¥ 1,800.00</td>
</tr>
<tr>
<td>月度净利润</td>
<td id="netProfitCell">¥ 33.00</td>
</tr>
<tr>
<td>投资回收期</td>
<td id="paybackCell">54.5 个月</td>
</tr>
<tr>
<td>年化投资回报率</td>
<td id="annualRoiCell">22.0%</td>
</tr>
</tbody>
</table>
<p class="note">提示若月度净利润≤0则投资回收期视为“尚无法回收”请通过提升日均回收量或优化成本结构来改进模型。</p>
</section>
</div>
<script>
// 工具函数安全读取输入值若为空则返回0
function getValue(id) {
const value = parseFloat(document.getElementById(id).value);
return Number.isFinite(value) ? value : 0;
}
// 工具函数:格式化为货币展示
function formatCurrency(value) {
return `¥ ${value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
}
// 工具函数:格式化数值,保留一位小数
function formatNumber(value) {
return value.toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 });
}
// 核心计算逻辑
function recalc() {
const dailyCardboard = getValue("dailyCardboard");
const dailyPet = getValue("dailyPet");
const days = getValue("daysPerMonth");
const buyCardboard = getValue("buyPriceCardboard");
const sellCardboard = getValue("sellPriceCardboard");
const buyPet = getValue("buyPricePet");
const sellPet = getValue("sellPricePet");
const siteFeePercent = getValue("siteFeePercent") / 100;
const logisticsCost = getValue("logisticsCost");
const maintenanceCost = getValue("maintenanceCost");
const otherCost = getValue("otherCost");
const equipmentCost = getValue("equipmentCost");
const deploymentCost = getValue("deploymentCost");
const monthlyCardboardKg = dailyCardboard * days;
const monthlyPetKg = dailyPet * days;
const monthlyTotalKg = monthlyCardboardKg + monthlyPetKg;
const payoutCardboard = monthlyCardboardKg * buyCardboard;
const payoutPet = monthlyPetKg * buyPet;
const payoutTotal = payoutCardboard + payoutPet;
const saleCardboard = monthlyCardboardKg * sellCardboard;
const salePet = monthlyPetKg * sellPet;
const saleTotal = saleCardboard + salePet;
const grossCardboard = saleCardboard - payoutCardboard;
const grossPet = salePet - payoutPet;
const grossTotal = grossCardboard + grossPet;
const siteFee = payoutTotal * siteFeePercent;
const fixedCostTotal = siteFee + logisticsCost + maintenanceCost + otherCost;
const monthlyNetProfit = grossTotal - fixedCostTotal;
const totalInvestment = equipmentCost + deploymentCost;
const annualNetProfit = monthlyNetProfit * 12;
const paybackMonths = monthlyNetProfit > 0 ? totalInvestment / monthlyNetProfit : Infinity;
const annualROI = monthlyNetProfit > 0 ? (annualNetProfit / totalInvestment) * 100 : 0;
// 更新表格及摘要展示
document.getElementById("monthlyCardboardKg").textContent = formatNumber(monthlyCardboardKg);
document.getElementById("monthlyPetKg").textContent = formatNumber(monthlyPetKg);
document.getElementById("monthlyTotalKg").textContent = formatNumber(monthlyTotalKg);
document.getElementById("payoutCardboard").textContent = formatCurrency(payoutCardboard);
document.getElementById("payoutPet").textContent = formatCurrency(payoutPet);
document.getElementById("payoutTotal").textContent = formatCurrency(payoutTotal);
document.getElementById("saleCardboard").textContent = formatCurrency(saleCardboard);
document.getElementById("salePet").textContent = formatCurrency(salePet);
document.getElementById("saleTotal").textContent = formatCurrency(saleTotal);
document.getElementById("grossCardboard").textContent = formatCurrency(grossCardboard);
document.getElementById("grossPet").textContent = formatCurrency(grossPet);
document.getElementById("grossTotal").textContent = formatCurrency(grossTotal);
document.getElementById("siteFee").textContent = formatCurrency(siteFee);
document.getElementById("logisticsCostCell").textContent = formatCurrency(logisticsCost);
document.getElementById("maintenanceCostCell").textContent = formatCurrency(maintenanceCost);
document.getElementById("otherCostCell").textContent = formatCurrency(otherCost);
document.getElementById("fixedCostTotal").innerHTML = `<strong>${formatCurrency(fixedCostTotal)}</strong>`;
document.getElementById("totalInvestment").textContent = formatCurrency(totalInvestment);
const netProfitLabel = formatCurrency(monthlyNetProfit);
document.getElementById("monthlyNetProfit").textContent = netProfitLabel;
document.getElementById("netProfitCell").textContent = netProfitLabel;
if (monthlyNetProfit > 0) {
const paybackText = `${paybackMonths.toFixed(1)} 个月`;
const annualRoiText = `${annualROI.toFixed(1)}%`;
document.getElementById("paybackPeriod").textContent = paybackText;
document.getElementById("annualROI").textContent = annualRoiText;
document.getElementById("paybackCell").textContent = paybackText;
document.getElementById("annualRoiCell").textContent = annualRoiText;
} else {
const warningText = "尚无法回收";
document.getElementById("paybackPeriod").textContent = warningText;
document.getElementById("paybackCell").textContent = warningText;
document.getElementById("annualROI").textContent = "0.0%";
document.getElementById("annualRoiCell").textContent = "0.0%";
}
}
// 监听所有输入框,实时刷新
document.querySelectorAll("input[type='number']").forEach((input) => {
input.addEventListener("input", recalc);
});
// 初始化计算一次,确保默认值正确呈现
recalc();
</script>
</body>
</html>