You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hjjc-workbench-web/budget-lifecycle-animation....

655 lines
22 KiB

8 months ago
<!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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
color: white;
margin-bottom: 40px;
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.header p {
font-size: 1.2em;
opacity: 0.9;
}
.animation-container {
background: white;
border-radius: 20px;
padding: 40px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
.stage {
display: none;
text-align: center;
animation: fadeInUp 0.8s ease-out;
}
.stage.active {
display: block;
}
.stage-icon {
width: 120px;
height: 120px;
margin: 0 auto 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 3em;
color: white;
position: relative;
animation: pulse 2s infinite;
}
.stage-icon::after {
content: '';
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
border: 3px solid;
border-radius: 50%;
opacity: 0.3;
animation: ripple 2s infinite;
}
.stage-1 .stage-icon { background: linear-gradient(45deg, #ff6b6b, #ee5a24); }
.stage-2 .stage-icon { background: linear-gradient(45deg, #4ecdc4, #44a08d); }
.stage-3 .stage-icon { background: linear-gradient(45deg, #45b7d1, #96c93d); }
.stage-4 .stage-icon { background: linear-gradient(45deg, #f9ca24, #f0932b); }
.stage-5 .stage-icon { background: linear-gradient(45deg, #6c5ce7, #a29bfe); }
.stage-title {
font-size: 2em;
color: #2c3e50;
margin-bottom: 20px;
font-weight: bold;
}
.stage-description {
font-size: 1.1em;
color: #7f8c8d;
line-height: 1.6;
margin-bottom: 30px;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.data-flow {
display: flex;
justify-content: center;
align-items: center;
margin: 40px 0;
flex-wrap: wrap;
gap: 20px;
}
.data-node {
background: white;
border: 3px solid #e74c3c;
border-radius: 15px;
padding: 20px;
min-width: 200px;
text-align: center;
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
transform: scale(0);
animation: scaleIn 0.6s ease-out forwards;
animation-delay: 0.3s;
}
.data-node.connected {
border-color: #27ae60;
background: linear-gradient(135deg, #d5f4e6, #e8f8f5);
}
.data-node h4 {
color: #2c3e50;
margin-bottom: 10px;
font-size: 1.1em;
}
.data-node p {
color: #7f8c8d;
font-size: 0.9em;
}
.connection-line {
width: 60px;
height: 3px;
background: linear-gradient(90deg, #e74c3c, #27ae60);
transform: scaleX(0);
animation: expandLine 0.8s ease-out forwards;
animation-delay: 0.6s;
}
.progress-bar {
width: 100%;
height: 8px;
background: #ecf0f1;
border-radius: 4px;
margin: 30px 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #ff6b6b, #4ecdc4, #45b7d1, #f9ca24, #6c5ce7);
width: 0%;
transition: width 1s ease-in-out;
border-radius: 4px;
}
.controls {
text-align: center;
margin-top: 30px;
}
.btn {
background: linear-gradient(45deg, #667eea, #764ba2);
color: white;
border: none;
padding: 15px 30px;
border-radius: 25px;
font-size: 1.1em;
cursor: pointer;
margin: 0 10px;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0,0,0,0.3);
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
.budget-data {
background: #f8f9fa;
border-radius: 15px;
padding: 30px;
margin: 30px 0;
border-left: 5px solid #667eea;
}
.budget-data h3 {
color: #2c3e50;
margin-bottom: 20px;
font-size: 1.3em;
}
.data-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-top: 20px;
}
.data-item {
background: white;
padding: 15px;
border-radius: 10px;
border: 1px solid #e9ecef;
}
.data-item label {
font-weight: bold;
color: #495057;
display: block;
margin-bottom: 5px;
}
.data-item span {
color: #6c757d;
}
.data-item.highlight {
background: linear-gradient(135deg, #fff3cd, #ffeaa7);
border-color: #ffc107;
animation: highlight 1s ease-in-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes ripple {
0% { transform: scale(1); opacity: 0.3; }
100% { transform: scale(1.3); opacity: 0; }
}
@keyframes scaleIn {
from { transform: scale(0); }
to { transform: scale(1); }
}
@keyframes expandLine {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
@keyframes highlight {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
.flow-arrow {
font-size: 2em;
color: #667eea;
margin: 20px 0;
animation: bounce 1s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-10px); }
60% { transform: translateY(-5px); }
}
@media (max-width: 768px) {
.container { padding: 10px; }
.animation-container { padding: 20px; }
.stage-icon { width: 80px; height: 80px; font-size: 2em; }
.stage-title { font-size: 1.5em; }
.data-flow { flex-direction: column; }
.connection-line { width: 3px; height: 40px; }
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>💰 预算模型数据生命周期演示</h1>
<p>展示预算数据从产生到审核的完整流程</p>
</div>
<div class="animation-container">
<!-- 进度条 -->
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<!-- 阶段1预算产生 -->
<div class="stage stage-1 active" id="stage1">
<div class="stage-icon">📊</div>
<h2 class="stage-title">阶段1预算产生</h2>
<p class="stage-description">
年度预算计划启动,各部门提交预算需求,系统生成初始预算模型数据
</p>
<div class="budget-data">
<h3>📋 预算基础数据</h3>
<div class="data-grid">
<div class="data-item highlight">
<label>预算年度</label>
<span>2025年</span>
</div>
<div class="data-item highlight">
<label>总预算金额</label>
<span>¥5,000,000</span>
</div>
<div class="data-item highlight">
<label>预算类型</label>
<span>部门运营预算</span>
</div>
<div class="data-item highlight">
<label>创建时间</label>
<span>2024-12-01</span>
</div>
</div>
</div>
</div>
<!-- 阶段2预算分解 -->
<div class="stage stage-2" id="stage2">
<div class="stage-icon">🔧</div>
<h2 class="stage-title">阶段2预算分解</h2>
<p class="stage-description">
将总预算按部门、项目、科目等维度进行分解,形成详细的预算分配方案
</p>
<div class="data-flow">
<div class="data-node" data-node="1">
<h4>技术部</h4>
<p>¥2,000,000</p>
</div>
<div class="connection-line"></div>
<div class="data-node" data-node="2">
<h4>市场部</h4>
<p>¥1,500,000</p>
</div>
<div class="connection-line"></div>
<div class="data-node" data-node="3">
<h4>运营部</h4>
<p>¥1,000,000</p>
</div>
<div class="connection-line"></div>
<div class="data-node" data-node="4">
<h4>财务部</h4>
<p>¥500,000</p>
</div>
</div>
</div>
<!-- 阶段3关联模型数据填充 -->
<div class="stage stage-3" id="stage3">
<div class="stage-icon">🔗</div>
<h2 class="stage-title">阶段3关联模型数据填充</h2>
<p class="stage-description">
建立预算数据与其他业务系统的关联关系,填充执行计划、资源配置等详细信息
</p>
<div class="budget-data">
<h3>🔗 关联数据模型</h3>
<div class="data-grid">
<div class="data-item">
<label>项目关联</label>
<span>技术研发项目A、B、C</span>
</div>
<div class="data-item">
<label>合同关联</label>
<span>设备采购合同、服务合同</span>
</div>
<div class="data-item">
<label>人员关联</label>
<span>项目经理、财务负责人</span>
</div>
<div class="data-item">
<label>时间关联</label>
<span>Q1-Q4执行计划</span>
</div>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="data-flow">
<div class="data-node connected" data-node="1">
<h4>预算执行计划</h4>
<p>按月分解执行</p>
</div>
<div class="connection-line"></div>
<div class="data-node connected" data-node="2">
<h4>资源分配</h4>
<p>人力、物力配置</p>
</div>
<div class="connection-line"></div>
<div class="data-node connected" data-node="3">
<h4>风险控制</h4>
<p>预算超支预警</p>
</div>
</div>
</div>
<!-- 阶段4预算执行 -->
<div class="stage stage-4" id="stage4">
<div class="stage-icon"></div>
<h2 class="stage-title">阶段4预算执行</h2>
<p class="stage-description">
预算开始执行,系统实时监控预算使用情况,记录每笔支出和收入
</p>
<div class="budget-data">
<h3>📈 执行进度监控</h3>
<div class="data-grid">
<div class="data-item">
<label>已使用金额</label>
<span>¥2,800,000</span>
</div>
<div class="data-item">
<label>剩余金额</label>
<span>¥2,200,000</span>
</div>
<div class="data-item">
<label>执行进度</label>
<span>56%</span>
</div>
<div class="data-item">
<label>执行状态</label>
<span>正常执行中</span>
</div>
</div>
</div>
</div>
<!-- 阶段5预算审核 -->
<div class="stage stage-5" id="stage5">
<div class="stage-icon"></div>
<h2 class="stage-title">阶段5预算审核</h2>
<p class="stage-description">
预算执行完成后,进入审核阶段,财务部门进行最终审核确认
</p>
<div class="budget-data">
<h3>✅ 审核结果</h3>
<div class="data-grid">
<div class="data-item highlight">
<label>审核状态</label>
<span>✅ 已通过</span>
</div>
<div class="data-item highlight">
<label>审核人</label>
<span>财务总监</span>
</div>
<div class="data-item highlight">
<label>审核时间</label>
<span>2025-01-15</span>
</div>
<div class="data-item highlight">
<label>审核意见</label>
<span>预算执行规范,数据完整</span>
</div>
</div>
</div>
<div class="flow-arrow">🎉</div>
<div class="budget-data" style="background: linear-gradient(135deg, #d4edda, #c3e6cb); border-left-color: #28a745;">
<h3 style="color: #155724;">🎯 生命周期完成</h3>
<p style="color: #155724; text-align: center; font-size: 1.1em;">
预算模型数据已成功完成从产生到审核的完整生命周期!
<br>数据将被归档并作为下一年度预算编制的参考依据。
</p>
</div>
</div>
</div>
<div class="controls">
<button class="btn" id="prevBtn" onclick="previousStage()" disabled>⬅️ 上一步</button>
<button class="btn" id="nextBtn" onclick="nextStage()">下一步 ➡️</button>
<button class="btn" onclick="resetAnimation()">🔄 重新开始</button>
</div>
</div>
<script>
let currentStage = 1;
const totalStages = 5;
function showStage(stageNumber) {
// 隐藏所有阶段
for (let i = 1; i <= totalStages; i++) {
document.getElementById(`stage${i}`).classList.remove('active');
}
// 显示当前阶段
document.getElementById(`stage${stageNumber}`).classList.add('active');
// 更新进度条
const progress = ((stageNumber - 1) / (totalStages - 1)) * 100;
document.getElementById('progressFill').style.width = progress + '%';
// 更新按钮状态
document.getElementById('prevBtn').disabled = stageNumber === 1;
document.getElementById('nextBtn').disabled = stageNumber === totalStages;
// 特殊动画效果
if (stageNumber === 2) {
setTimeout(() => {
animateDataNodes();
}, 500);
} else if (stageNumber === 3) {
setTimeout(() => {
animateConnections();
}, 500);
} else if (stageNumber === 4) {
setTimeout(() => {
animateProgress();
}, 500);
} else if (stageNumber === 5) {
setTimeout(() => {
animateCompletion();
}, 500);
}
}
function nextStage() {
if (currentStage < totalStages) {
currentStage++;
showStage(currentStage);
}
}
function previousStage() {
if (currentStage > 1) {
currentStage--;
showStage(currentStage);
}
}
function resetAnimation() {
currentStage = 1;
showStage(currentStage);
// 重置所有动画状态
const dataNodes = document.querySelectorAll('.data-node');
dataNodes.forEach(node => {
node.classList.remove('connected');
node.style.animation = 'none';
setTimeout(() => {
node.style.animation = '';
}, 10);
});
}
function animateDataNodes() {
const dataNodes = document.querySelectorAll('.data-node');
dataNodes.forEach((node, index) => {
setTimeout(() => {
node.classList.add('connected');
}, index * 200);
});
}
function animateConnections() {
const connectionLines = document.querySelectorAll('.connection-line');
connectionLines.forEach((line, index) => {
setTimeout(() => {
line.style.animation = 'expandLine 0.8s ease-out forwards';
}, index * 300);
});
}
function animateProgress() {
const progressItems = document.querySelectorAll('.data-item');
progressItems.forEach((item, index) => {
setTimeout(() => {
item.classList.add('highlight');
}, index * 200);
});
}
function animateCompletion() {
const completionItems = document.querySelectorAll('.data-item.highlight');
completionItems.forEach((item, index) => {
setTimeout(() => {
item.style.animation = 'highlight 1s ease-in-out';
}, index * 150);
});
}
// 键盘控制
document.addEventListener('keydown', function(e) {
if (e.key === 'ArrowRight' || e.key === ' ') {
e.preventDefault();
nextStage();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
previousStage();
}
});
// 触摸控制(移动端)
let touchStartX = 0;
document.addEventListener('touchstart', function(e) {
touchStartX = e.touches[0].clientX;
});
document.addEventListener('touchend', function(e) {
const touchEndX = e.changedTouches[0].clientX;
const diff = touchStartX - touchEndX;
if (Math.abs(diff) > 50) {
if (diff > 0) {
nextStage();
} else {
previousStage();
}
}
});
// 初始化
showStage(1);
</script>
</body>
</html>