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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!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>