370 lines
24 KiB
HTML
370 lines
24 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>回报率预测计算器</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<script>
|
||
tailwind.config = {
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
primary: '#2563eb',
|
||
secondary: '#38bdf8'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
</head>
|
||
<body class="bg-gray-50 font-sans text-gray-800">
|
||
<div class="min-h-screen px-4 py-6 md:px-8 md:py-8">
|
||
<div class="max-w-6xl mx-auto bg-white/95 shadow-xl rounded-2xl p-6 md:p-8">
|
||
<header class="mb-8">
|
||
<h1 class="text-2xl md:text-3xl font-bold text-gray-900 mb-2">回报率预测计算器</h1>
|
||
<p class="text-gray-600 text-sm md:text-base">根据《回报率预测》文档的假设提供默认值,可随场景调整实时查看财务指标。</p>
|
||
</header>
|
||
|
||
<!-- Summary Cards -->
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
||
<div class="bg-gradient-to-br from-primary to-secondary rounded-xl p-5 text-white">
|
||
<h2 class="text-xs md:text-sm uppercase tracking-wider font-semibold mb-3">月度净利润</h2>
|
||
<div id="monthlyNetProfit" class="text-2xl md:text-3xl font-bold mb-2">¥ 33.00</div>
|
||
<p class="text-xs text-blue-100">= 月毛利 - 固定运营成本</p>
|
||
</div>
|
||
<div class="bg-gradient-to-br from-primary to-secondary rounded-xl p-5 text-white">
|
||
<h2 class="text-xs md:text-sm uppercase tracking-wider font-semibold mb-3">投资回收期</h2>
|
||
<div id="paybackPeriod" class="text-2xl md:text-3xl font-bold mb-2">54.5 个月</div>
|
||
<p class="text-xs text-blue-100">= 总投资 / 月净利润</p>
|
||
</div>
|
||
<div class="bg-gradient-to-br from-primary to-secondary rounded-xl p-5 text-white">
|
||
<h2 class="text-xs md:text-sm uppercase tracking-wider font-semibold mb-3">年化 ROI</h2>
|
||
<div id="annualROI" class="text-2xl md:text-3xl font-bold mb-2">22.0%</div>
|
||
<p class="text-xs text-blue-100">= (年净利润 / 总投资) × 100%</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Input Sections -->
|
||
<section class="mb-8">
|
||
<h3 class="text-lg md:text-xl font-semibold text-gray-900 mb-4">核心量化假设</h3>
|
||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">日均废纸板回收量 (公斤)</span>
|
||
<input id="dailyCardboard" type="number" min="0" step="0.1" value="20"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">日均塑料瓶回收量 (公斤)</span>
|
||
<input id="dailyPet" type="number" min="0" step="0.1" value="10"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">月计费天数 (天)</span>
|
||
<input id="daysPerMonth" type="number" min="1" step="1" value="30"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">运营站点数量 (个)</span>
|
||
<input id="siteCount" type="number" min="1" step="1" value="5"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">废纸板回收价 ¥/公斤 (给用户)</span>
|
||
<input id="buyPriceCardboard" type="number" min="0" step="0.01" value="0.8"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">废纸板出售价 ¥/公斤 (给打包站)</span>
|
||
<input id="sellPriceCardboard" type="number" min="0" step="0.01" value="1.2"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">塑料瓶回收价 ¥/公斤 (给用户)</span>
|
||
<input id="buyPricePet" type="number" min="0" step="0.01" value="1.4"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">塑料瓶出售价 ¥/公斤 (给打包站)</span>
|
||
<input id="sellPricePet" type="number" min="0" step="0.01" value="2.0"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="mb-8">
|
||
<h3 class="text-lg md:text-xl font-semibold text-gray-900 mb-4">运营及投入假设</h3>
|
||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">场地合作分成 (占销售总收入 %)</span>
|
||
<input id="siteFeePercent" type="number" min="0" step="0.1" value="10"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">月物流清运成本 (¥)</span>
|
||
<input id="logisticsCost" type="number" min="0" step="1" value="220"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">设备维护与网络费 (¥/月)</span>
|
||
<input id="maintenanceCost" type="number" min="0" step="1" value="27"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">其他运营成本 (¥/月)</span>
|
||
<input id="otherCost" type="number" min="0" step="1" value="50"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">单站设备投入 (¥)</span>
|
||
<input id="equipmentCost" type="number" min="0" step="10" value="1500"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
<label class="block">
|
||
<span class="text-sm font-medium text-gray-700 mb-2 block">部署及安装成本 (¥)</span>
|
||
<input id="deploymentCost" type="number" min="0" step="10" value="300"
|
||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-base focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-colors" />
|
||
</label>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Results Section -->
|
||
<section class="space-y-6">
|
||
<h3 class="text-lg md:text-xl font-semibold text-gray-900">产出指标</h3>
|
||
|
||
<!-- 产出指标表格 -->
|
||
<div class="overflow-x-auto">
|
||
<table class="w-full border-collapse bg-white rounded-lg overflow-hidden shadow-sm">
|
||
<thead>
|
||
<tr class="bg-blue-50">
|
||
<th class="text-left px-4 py-3 text-sm font-semibold text-gray-900">指标</th>
|
||
<th class="text-right px-4 py-3 text-sm font-semibold text-gray-900">废纸板</th>
|
||
<th class="text-right px-4 py-3 text-sm font-semibold text-gray-900">塑料瓶</th>
|
||
<th class="text-right px-4 py-3 text-sm font-semibold text-gray-900">合计</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="divide-y divide-gray-200">
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">月度回收量 (公斤)</td>
|
||
<td id="monthlyCardboardKg" class="px-4 py-3 text-sm text-right text-gray-600">600.0</td>
|
||
<td id="monthlyPetKg" class="px-4 py-3 text-sm text-right text-gray-600">300.0</td>
|
||
<td id="monthlyTotalKg" class="px-4 py-3 text-sm text-right font-medium text-gray-900">900.0</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">给用户回收金 (¥)</td>
|
||
<td id="payoutCardboard" class="px-4 py-3 text-sm text-right text-gray-600">¥ 480.00</td>
|
||
<td id="payoutPet" class="px-4 py-3 text-sm text-right text-gray-600">¥ 420.00</td>
|
||
<td id="payoutTotal" class="px-4 py-3 text-sm text-right font-medium text-gray-900">¥ 900.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">销售收入 (¥)</td>
|
||
<td id="saleCardboard" class="px-4 py-3 text-sm text-right text-gray-600">¥ 720.00</td>
|
||
<td id="salePet" class="px-4 py-3 text-sm text-right text-gray-600">¥ 600.00</td>
|
||
<td id="saleTotal" class="px-4 py-3 text-sm text-right font-medium text-gray-900">¥ 1,320.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">毛利 (¥)</td>
|
||
<td id="grossCardboard" class="px-4 py-3 text-sm text-right text-gray-600">¥ 240.00</td>
|
||
<td id="grossPet" class="px-4 py-3 text-sm text-right text-gray-600">¥ 180.00</td>
|
||
<td id="grossTotal" class="px-4 py-3 text-sm text-right font-medium text-primary">¥ 420.00</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- 成本拆解表格 -->
|
||
<div class="overflow-x-auto">
|
||
<table class="w-full border-collapse bg-white rounded-lg overflow-hidden shadow-sm">
|
||
<thead>
|
||
<tr class="bg-blue-50">
|
||
<th class="text-left px-4 py-3 text-sm font-semibold text-gray-900">成本拆解</th>
|
||
<th class="text-right px-4 py-3 text-sm font-semibold text-gray-900">金额 (¥)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="divide-y divide-gray-200">
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">场地合作费</td>
|
||
<td id="siteFee" class="px-4 py-3 text-sm text-right text-gray-600">¥ 90.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">月物流清运成本</td>
|
||
<td id="logisticsCostCell" class="px-4 py-3 text-sm text-right text-gray-600">¥ 220.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">设备维护与网络费</td>
|
||
<td id="maintenanceCostCell" class="px-4 py-3 text-sm text-right text-gray-600">¥ 27.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">其他运营成本</td>
|
||
<td id="otherCostCell" class="px-4 py-3 text-sm text-right text-gray-600">¥ 50.00</td>
|
||
</tr>
|
||
<tr class="bg-gray-50">
|
||
<td class="px-4 py-3 text-sm font-semibold text-gray-900">固定成本合计</td>
|
||
<td id="fixedCostTotal" class="px-4 py-3 text-sm text-right font-semibold text-gray-900">¥ 387.00</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- 投资与回报表格 -->
|
||
<div class="overflow-x-auto">
|
||
<table class="w-full border-collapse bg-white rounded-lg overflow-hidden shadow-sm">
|
||
<thead>
|
||
<tr class="bg-blue-50">
|
||
<th class="text-left px-4 py-3 text-sm font-semibold text-gray-900">投资与回报</th>
|
||
<th class="text-right px-4 py-3 text-sm font-semibold text-gray-900">金额 / 指标</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="divide-y divide-gray-200">
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">总投资 (Capex)</td>
|
||
<td id="totalInvestment" class="px-4 py-3 text-sm text-right text-gray-600">¥ 1,800.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">月度净利润</td>
|
||
<td id="netProfitCell" class="px-4 py-3 text-sm text-right font-medium text-primary">¥ 33.00</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">投资回收期</td>
|
||
<td id="paybackCell" class="px-4 py-3 text-sm text-right text-gray-600">54.5 个月</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="px-4 py-3 text-sm text-gray-900">年化投资回报率</td>
|
||
<td id="annualRoiCell" class="px-4 py-3 text-sm text-right font-medium text-green-600">22.0%</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||
<p class="text-sm text-yellow-800">
|
||
<span class="font-semibold">提示:</span>
|
||
若月度净利润≤0,则投资回收期视为"尚无法回收",请通过提升日均回收量或优化成本结构来改进模型。
|
||
</p>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</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 siteCount = Math.max(getValue("siteCount"), 0);
|
||
|
||
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 * siteCount;
|
||
const monthlyPetKg = dailyPet * days * siteCount;
|
||
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 logisticsCostTotal = logisticsCost * siteCount;
|
||
const maintenanceCostTotal = maintenanceCost * siteCount;
|
||
const otherCostTotal = otherCost * siteCount;
|
||
const siteFee = saleTotal * siteFeePercent;
|
||
const fixedCostTotal = siteFee + logisticsCostTotal + maintenanceCostTotal + otherCostTotal;
|
||
const monthlyNetProfit = grossTotal - fixedCostTotal;
|
||
|
||
const totalInvestmentPerSite = equipmentCost + deploymentCost;
|
||
const totalInvestment = totalInvestmentPerSite * siteCount;
|
||
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(logisticsCostTotal);
|
||
document.getElementById("maintenanceCostCell").textContent = formatCurrency(maintenanceCostTotal);
|
||
document.getElementById("otherCostCell").textContent = formatCurrency(otherCostTotal);
|
||
document.getElementById("fixedCostTotal").textContent = formatCurrency(fixedCostTotal);
|
||
|
||
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>
|