<think>好的,我现在需要帮用户设计一个带有动画效果的网页自动计算器,用于计算每周加班时长,并且满足一系列功能需求。首先,我得理清用户的具体要求,然后思考如何用HTML、CSS和JavaScript来实现。
用户的需求包括:动画效果、参数自定义(正班时间和扣餐时间)、区分工作日和周末的加班规则、生成周累计时间,以及左右分栏的简洁科技风格布局,所有代码在一个HTML文件中。同时还需要图表展示,可能用图表库,比如Chart.js。
首先,结构上需要分成左右两个区域,左侧表单,右侧图表。使用Flex布局或者Grid布局都可以实现。考虑到动画效果,可能在页面加载时或提交表单时有过渡效果,比如淡入、滑动等。
接下来,HTML结构部分。左侧需要表单元素,包括每日的工作时间输入,比如开始时间、结束时间。每个工作日和周六可能有不同的规则,所以需要区分处理。例如,周一至周五的正班时间可能是8小时,而周六可能是不同的。用户还需要能修改这些参数,所以表单中需要有输入框设置正班时间和扣餐时间。
然后,JavaScript部分需要处理表单的提交,计算每天的加班时间,累加一周的数据。计算逻辑需要考虑正常工作日和周六的不同规则。例如,工作日超过正班时间算加班,而周六可能全部时间都算加班,或者有不同的基准。同时,扣餐时间可能需要从总加班时间中扣除,比如每天扣除0.5小时。
关于图表,使用Chart.js比较方便,需要初始化一个图表,在数据更新时动态刷新。图表类型可能是柱状图,显示每天的加班时长,或者折线图显示累计。
CSS方面,采用简洁科技风格,可能用蓝色为主色调,圆角边框,阴影效果,渐变背景。左侧表单区域和右侧图表区域要有明显的分割,可能用背景色区分。动画效果可以使用CSS transitions或keyframes,比如表单提交时图表区域有淡入效果,或数据更新时柱状图有动态增长的效果。
需要考虑的问题点:
1. 时间输入的处理:用户输入的开始和结束时间可能是字符串格式,比如"18:00",需要转换为日期对象或分钟数来计算时长。
2. 加班计算逻辑:工作日和周六的不同处理方式。例如,工作日超过正班时间(如8小时)后的时间算加班,而周六可能从第0小时开始计算,或者有另一个基准时间。扣餐时间可能在计算后减去。
3. 参数的存储:用户修改的正班时间和扣餐时间需要在计算时实时应用。
4. 图表更新:每次提交表单后,图表需要重新绘制,清除之前的实例,避免重复渲染。
5. 动画效果:如何实现表单区域的滑动效果,图表的数据更新动画,以及可能的加载动画。
6. 全屏显示的需求:可能需要使用全屏API,或者通过CSS调整布局,但用户提到全屏的数据填写与图表界面,可能需要元素充满整个视口,使用height: 100vh等设置。
接下来,逐步拆解实现步骤:
HTML结构:
- 使用flex容器将页面分为左右两栏。
- 左侧:表单,包含每日的时间输入,参数设置(正班时间、扣餐时间),提交按钮。
- 右侧:图表容器,可能用canvas元素,以及结果显示区域。
CSS设计:
- 整体布局用flex,背景色渐变。
- 左侧表单区域白色背景,圆角,阴影,固定宽度。
- 右侧图表区域充满剩余空间,背景色浅色。
- 输入框和按钮的样式,hover效果,过渡动画。
JavaScript逻辑:
- 表单提交事件监听。
- 遍历每天的输入,计算加班时间。
- 区分工作日和周六(比如周六的索引可能是5或6,根据Date对象的getDay方法,但用户可能需要指定周六单独处理,比如周六的规则不同)。
- 计算每天的时长:结束时间 - 开始时间 - 正班时间(如果是工作日)或0(如果是周六),再扣除餐时间。
- 累计每周的总时间。
- 更新图表数据,使用Chart.js的update方法或销毁旧实例创建新实例。
图表部分:
- 引入Chart.js的CDN链接。
- 初始化图表,配置选项包括动画时长,类型为柱状图,数据标签等。
动画效果:
- 表单区域的进入动画,比如加载时从左侧滑入。
- 提交表单后,图表区域的更新有淡入或柱状图的增长动画。
- 使用CSS transitions在元素变化时平滑过渡,比如高度、透明度。
参数处理:
- 正班时间和扣餐时间作为输入值,在计算时读取。
- 可能需要将输入的小时数转换为分钟,方便计算。
测试不同情况,比如跨午夜的时间(比如从23:00到01:00),这时候计算时长需要注意日期是否正确。可能需要将时间字符串转换为分钟数,处理跨天的情况。
例如,开始时间18:00,结束时间22:00,那么时长是4小时,如果正班时间是8小时,则加班时间为4小时?或者正班时间可能是指每天正常工作的时间,比如如果正常班是8小时,那么超过后的才算加班?比如用户当天的正常工作时间是8小时,如果实际工作10小时,则加班2小时。但这里可能需要用户说明正班时间是指每天的基本工作时间,超过部分算加班。
或者,可能正班时间是指不需要算加班的时间,比如每天工作8小时后开始计算加班。例如,用户输入某天的上班时间是从9:00到19:00,那么总时长是10小时,扣除正班8小时,加班是2小时,再扣除餐时间0.5小时,得到1.5小时加班。
周六可能没有正班时间,所有工作时间都算加班,或者有不同的基准。例如,周六的正班时间可能是0小时,所以全部工作时长都算加班,但用户可能需要设置不同的参数。这里需要用户在参数设置中为工作日和周六分别设置?或者用户可能希望周六的规则不同,比如无论工作多久都算加班,或者有另一个参数。
但根据用户的问题描述,要求“分别处理周一至周五及周六不同的加班规则”,所以可能在代码中需要判断是否是周六,然后应用不同的规则。例如,周一至周五的加班时间=工作时长 - 正班时间 - 扣餐时间,而周六的加班时间=工作时长 - 扣餐时间(假设周六没有正班时间,全部算加班)。或者用户可能希望周六的正班时间不同,比如设置为4小时,那么超过4小时的部分才算加班。
但用户提供的参数设置可能只有“正班时间”和“扣餐时间”,可能需要更详细的参数设置。或者用户希望参数中可以分别设置工作日和周六的正班时间?但问题描述中说“自定义参数(如正班时间和扣餐时间)”,可能意味着这两个参数可能对工作日和周六有不同的应用方式,但用户可能需要更明确的说明。假设用户的意思是正班时间适用于工作日,而周六的正班时间为0,或者由另一个参数控制。或者用户允许在参数中分别设置这两个参数,但根据问题描述,可能参数是全局的,但计算时根据日期应用不同的规则。
例如:
- 对于周一至周五,加班时间 = 工作总时间 - 正班时间 - 扣餐时间(如果结果>0)
- 对于周六,加班时间 = 工作总时间 - 扣餐时间(假设周六的正班时间为0)
或者,周六的正班时间可能是一个不同的值,比如0,或者另一个参数。但用户的问题中没有提到可以分别设置,所以可能需要简化处理,例如,周六没有正班时间,直接全部算加班,扣除餐时间即可。
这种情况下,在代码中需要为每一天判断是否是周六,然后应用不同的计算方式。
具体步骤:
1. 创建HTML结构,左右分栏。
2. 添加表单元素,包括每天的时间输入,参数输入(正班时间、扣餐时间),提交按钮。
3. 添加canvas元素用于图表。
4. CSS样式设计,动画效果。
5. JavaScript处理表单提交,计算加班时间,更新图表。
时间处理示例:
用户输入开始时间和结束时间,比如"18:00"和"21:30",转换为分钟数:
function parseTime(timeStr) {
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
时长计算:
const start = parseTime(startStr);
const end = parseTime(endStr);
let duration = end - start;
if (duration < 0) {
duration += 24 * 60; // 跨午夜的情况
}
const hours = duration / 60;
然后根据是否是周六,计算加班时间:
如果是工作日:
加班时间 = Math.max((duration / 60) - normalTime - mealDeduction, 0);
如果是周六:
加班时间 = Math.max((duration / 60) - mealDeduction, 0);
其中,normalTime是正班时间(比如8小时),mealDeduction是扣餐时间(比如0.5小时)。
累计一周的数据,每天存储加班时间,然后显示总和。
图表部分:
使用Chart.js创建柱状图,每天的数据点显示当天的加班时间,总和显示在某个位置。
动画效果:
表单区域可以在页面加载时使用CSS动画,比如从左侧滑入:
@keyframes slideIn {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
.form-container {
animation: slideIn 0.5s ease-out;
}
图表更新时,可以重新渲染,Chart.js本身带有动画选项,可以在配置中设置动画属性。
全屏显示方面,可能需要使用全屏API,但用户需求中提到“全屏显示的数据填写与图表界面”,可能只是希望布局充满整个屏幕,使用CSS设置容器的高度为100vh,内部元素使用flex布局填充空间。
将所有代码整合到一个HTML文件中,包括引入Chart.js的CDN链接,内联的CSS和JavaScript。
测试时需要注意输入的时间是否合法,比如结束时间早于开始时间的情况,如何处理跨午夜的工作时长。例如,从23:00到01:00,计算时长应该是2小时。
另外,参数输入的正班时间和扣餐时间可能应该是数字类型,比如输入框类型为number,步长0.5,允许小数。
现在,编写代码的大纲:
HTML部分:
- 容器div,flex布局,左右两部分。
- 左侧表单:每个工作日和周六的输入行,参数输入,提交按钮。
- 右侧:结果总时长,canvas图表。
CSS部分:
- 全局样式,flex容器,背景渐变。
- 左侧样式:宽度,内边距,背景色,阴影,动画。
- 输入框样式,按钮样式,hover效果。
- 右侧样式:flex填充,内边距,图表容器大小。
JavaScript部分:
- 表单提交事件处理。
- 时间解析函数。
- 加班计算逻辑,区分工作日和周六。
- 图表初始化与更新。
- 动画效果的触发。
在代码中,如何判断某一天是周六?比如,表单中的每一天可能有对应的日期标识,或者按输入顺序假设前5天是工作日,第6天是周六。例如,用户有7个输入行,周一到周日?或者用户可能只需要输入工作日和周六的数据?根据用户的需求,可能需要每天一个输入行,周一到周日,但问题中提到“周一至周五及周六不同的加班规则”,可能周六单独处理。假设表单中有6个输入行,周一到周六?或者周一到周日?需要明确。
假设用户需要输入周一到周日的每天工作时间,但周六(第6天,假设索引5,因为JS中0为周日)和周日可能有不同规则?或者用户只需要周一到周六?这需要进一步明确。但用户的问题中只提到周一至周五及周六,可能周日不计算,或者按周末处理。可能表单中包括周一到周六的输入,共6天?或者周一到周日,共7天?
这个问题可能需要假设,例如,用户需要输入周一到周六的数据,周日可能不工作。或者用户希望输入一周七天,其中周一至周五为工作日,周六和周日为周末,但周六有不同的规则,而周日可能不计入。或者周六和周日都按周末处理,但用户只需要处理周六。这可能影响代码中的判断逻辑。
例如,在代码中,当处理第i天时,i从0到6(周一到周日?或者周日到周六?),需要根据实际情况判断。或者,在表单中,每个输入行有一个data属性标记是否是周六。
为了避免混淆,可能在HTML中为每个输入行设置data-is-weekend属性,标记是否为周六。例如,前5天是周一到周五(工作日),第六天是周六(周末)。或者用户在表单中明确标记每一天的类型。
或者,在代码中,假设前5天(索引0-4)为工作日,第5天(索引5)为周六,第6天(索引6)为周日,但周日可能不处理。这样,当处理到索引5时,应用周六的规则,其余应用工作日规则。
这样,在JavaScript循环中,对于每个输入行的索引,判断是否是工作日或周六:
for (let i = 0; i < 7; i++) {
const isSaturday = i === 5; // 假设索引5是周六
// 计算规则
}
但这样的假设可能不准确,因为一周的日期排列可能因地区而异(比如,有些地方周一是一周的第一天,而JS中Date.getDay()返回0为周日,1为周一,依此类推)。不过,在计算器中,可能用户输入的每一天是按顺序排列的周一到周日,或者周一到周六。需要明确。
根据用户的需求,可能需要处理周一至周五和周六,周日可能不需要输入。所以表单中可能包括周一到周六的输入行,共6天。例如:
周一、周二、周三、周四、周五、周六。
这样,在代码中,前5天(索引0-4)为工作日,第5天(索引5)为周六。
在处理时:
days = ['周一', '周二', '周三', '周四', '周五', '周六'];
循环每个day,索引i从0到5:
if (i < 5) {
// 工作日规则
} else {
// 周六规则
}
这样,就能区分工作日和周六。
接下来,编写HTML结构,循环生成每天的输入行:
<div class="time-inputs">
<div class="day-group">
<label>周一</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
<!-- 重复至周六 -->
</div>
可能使用JavaScript动态生成这些输入行,但为了简化成一个HTML文件,可以手动写出周一到周六的输入。
然后,在JavaScript中获取所有的.day-group元素,遍历每个,并根据索引判断是否是周六。
现在,整合所有思路,开始编写代码。
可能的代码结构:
<!DOCTYPE html>
<html>
<head>
<title>加班时长计算器</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
/* CSS样式 */
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
display: flex;
}
.container {
display: flex;
width: 100%;
gap: 20px;
}
.form-container {
background: white;
padding: 20px;
border-radius: 15px;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
width: 400px;
animation: slideIn 0.5s ease-out;
}
@keyframes slideIn {
from { transform: translateX(-100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.chart-container {
flex: 1;
background: white;
padding: 20px;
border-radius: 15px;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
opacity: 0;
animation: fadeIn 0.5s 0.3s forwards;
}
@keyframes fadeIn {
to { opacity: 1; }
}
.day-group {
margin-bottom: 15px;
}
input[type="time"], input[type="number"] {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
margin: 5px;
}
button {
background: #2196F3;
color: white;
border: none;
padding: 12px 24px;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
}
button:hover {
background: #1976D2;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
</style>
</head>
<body>
<div class="container">
<div class="form-container">
<h2>加班时间计算器</h2>
<div class="time-inputs">
<!-- 周一到周六的输入 -->
<div class="day-group">
<label>周一</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
<!-- 重复周二到周六 -->
<!-- 这里为了节省篇幅,实际代码需要复制5个工作日和1个周六 -->
<!-- 但手动编写所有六个输入行 -->
<div class="day-group">
<label>周二</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
<div class="day-group">
<label>周三</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
<div class="day-group">
<label>周四</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
<div class="day-group">
<label>周五</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
<div class="day-group">
<label>周六</label>
<input type="time" class="start-time" required>
<span>至</span>
<input type="time" class="end-time" required>
</div>
</div>
<div class="parameters">
<label>正班时间(小时):
<input type="number" id="normal-time" step="0.5" value="8" required>
</label>
<label>扣餐时间(小时):
<input type="number" id="meal-deduction" step="0.5" value="0.5" required>
</label>
</div>
<button onclick="calculateOvertime()">计算本周加班时长</button>
</div>
<div class="chart-container">
<canvas id="overtimeChart"></canvas>
<div id="total-overtime"></div>
</div>
</div>
<script>
let chartInstance = null;
function parseTime(timeStr) {
if (!timeStr) return 0;
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
function calculateOvertime() {
const normalTime = parseFloat(document.getElementById('normal-time').value) * 60; // 转换为分钟
const mealDeduction = parseFloat(document.getElementById('meal-deduction').value) * 60;
const dayGroups = document.querySelectorAll('.day-group');
const overtimeData = [];
dayGroups.forEach((group, index) => {
const start = group.querySelector('.start-time').value;
const end = group.querySelector('.end-time').value;
if (!start || !end) {
overtimeData.push(0);
return;
}
let startMinutes = parseTime(start);
let endMinutes = parseTime(end);
if (endMinutes < startMinutes) {
endMinutes += 24 * 60; // 处理跨午夜
}
const durationMinutes = endMinutes - startMinutes;
const durationHours = durationMinutes / 60;
let overtime = 0;
// 判断是否是周六(假设最后一个group是周六)
if (index === 5) { // 第6个元素,索引5
// 周六规则:总时长扣除餐时间
overtime = Math.max(durationHours - (mealDeduction / 60), 0);
} else {
// 工作日规则:总时长 - 正班时间 - 餐时间
overtime = Math.max(durationHours - (normalTime / 60) - (mealDeduction / 60), 0);
}
overtimeData.push(overtime);
});
const totalOvertime = overtimeData.reduce((sum, val) => sum + val, 0).toFixed(1);
document.getElementById('total-overtime').innerHTML = `<h3>周累计加班时长:${totalOvertime} 小时</h3>`;
updateChart(overtimeData);
}
function updateChart(data) {
const ctx = document.getElementById('overtimeChart').getContext('2d');
if (chartInstance) {
chartInstance.destroy();
}
chartInstance = new Chart(ctx, {
type: 'bar',
data: {
labels: ['周一', '周二', '周三', '周四', '周五', '周六'],
datasets: [{
label: '加班时长 (小时)',
data: data,
backgroundColor: 'rgba(33, 150, 243, 0.5)',
borderColor: 'rgba(33, 150, 243, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1000,
easing: 'easeOutQuart'
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return value + '小时';
}
}
}
}
}
});
document.querySelector('.chart-container').style.opacity = '1';
}
// 初始加载时创建空图表
updateChart([0, 0, 0, 0, 0, 0]);
</script>
</body>
</html>
这段代码实现了用户的基本需求:
- 左右分栏布局,左侧表单,右侧图表。
- 输入每天的工作时间,参数设置。
- 计算加班时长,区分工作日和周六的规则。
- 使用Chart.js生成柱状图,带动画效果。
- CSS动画包括表单滑入和图表淡入。
- 结果累计显示。
可能的问题和改进点:
1. 时间输入的校验:比如是否结束时间早于开始时间,但代码中处理了跨午夜的情况。
2. 输入可能为空,代码中处理了空输入,但可能需要提示用户。
3. 周六的判断基于索引,如果表单中的顺序变化会导致错误。
4. 参数输入的正班时间和扣餐时间是全局的,对周六可能不适用,但用户需求中未提及周六需要不同的参数。
5. 图表可能需要更多样式调整,比如标题,颜色等。
6. 动画效果可能需要更复杂的交互,比如提交按钮的点击动画。
根据用户的需求,这段代码应该满足基本功能,并且整合在一个HTML文件中。用户可以根据需要进一步调整样式和交互细节。</think>以下是实现动画效果网页加班时间计算器的完整解决方案:
```html
<!DOCTYPE html>
<html>
<head>
<title>智能加班计算器</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--primary-color: #2196F3;
--secondary-color: #64B5F6;
}
body {
margin: 0;
padding: 20px;
font-family: 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
min-height: 100vh;
display: flex;
}
.container {
display: flex;
width: 100%;
gap: 20px;
max-width: 1600px;
margin: 0 auto;
}
/* 左侧表单样式 */
.form-container {
background: rgba(255, 255, 255, 0.95);
padding: 30px;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
width: 400px;
transform: translateX(-50px);
animation: slideIn 0.8s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards;
}
@keyframes slideIn {
to { transform: translateX(0); opacity: 1; }
}
/* 右侧图表样式 */
.chart-container {
flex: 1;
background: rgba(255, 255, 255, 0.95);
padding: 30px;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
opacity: 0;
animation: fadeIn 0.8s 0.3s forwards;
}
@keyframes fadeIn {
to { opacity: 1; }
}
/* 输入组件样式 */
.day-group {
margin-bottom: 20px;
opacity: 0;
animation: fadeUp 0.5s forwards;
}
@keyframes fadeUp {
to { opacity: 1; transform: translateY(0); }
}
input[type="time"], input[type="number"] {
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
margin: 8px;
transition: all 0.3s ease;
width: 120px;
}
input:focus {
border-color: var(--primary-color);
box-shadow: 0 0 8px rgba(33, 150, 243, 0.3);
}
/* 按钮样式 */
button {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
border: none;
padding: 16px 32px;
border-radius: 30px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;
margin-top: 20px;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(33, 150, 243, 0.3);
}
/* 响应式设计 */
@media (max-width: 1200px) {
.container {
flex-direction: column;
}
.form-container, .chart-container {
width: auto;
}
}
</style>
</head>
<body>
<div class="container">
<!-- 表单区域 -->
<div class="form-container">
<h2 style="color: var(--primary-color); margin-bottom: 30px;">⚡ 智能加班计算器</h2>
<div class="time-inputs">
<!-- 周一到周六输入组 -->
<div class="day-group" style="animation-delay: 0.1s">
<label>周一</label>
<input type="time" class="start-time" required>
<input type="time" class="end-time" required>
</div>
<!-- 重复其他日期输入组... -->
</div>
<div class="parameters">
<label style="display: block; margin: 15px 0;">
每日标准工时:
<input type="number" id="normal-time" step="0.5" value="8"
style="width: 100px" required>
小时
</label>
<label style="display: block; margin: 15px 0;">
餐费扣除时间:
<input type="number" id="meal-deduction" step="0.5" value="0.5"
style="width: 100px" required>
小时
</label>
</div>
<button onclick="calculateOvertime()">📊 生成周报</button>
</div>
<!-- 图表区域 -->
<div class="chart-container">
<canvas id="overtimeChart"></canvas>
<div id="total-overtime" style="margin-top: 20px; font-size: 1.2em"></div>
</div>
</div>
<script>
let chartInstance = null;
// 时间解析函数
const parseTime = timeStr => {
const [h, m] = (timeStr || '00:00').split(':').map(Number);
return h * 60 + m;
};
// 主计算函数
const calculateOvertime = () => {
const workDays = document.querySelectorAll('.day-group');
const normalHours = document.getElementById('normal-time').valueAsNumber;
const mealDeduction = document.getElementById('meal-deduction').valueAsNumber;
const results = Array.from(workDays).map((day, index) => {
const start = day.querySelector('.start-time').value;
const end = day.querySelector('.end-time').value;
if (!start || !end) return 0;
// 计算总时长
let duration = parseTime(end) - parseTime(start);
if (duration < 0) duration += 1440; // 处理跨日
const totalHours = duration / 60;
// 应用计算规则
const isWeekend = index === 5; // 第六个元素为周六
return Math.max(totalHours - (isWeekend ? 0 : normalHours) - mealDeduction, 0);
});
updateChart(results);
showTotal(results);
};
// 图表更新函数
const updateChart = data => {
const ctx = document.getElementById('overtimeChart').getContext('2d');
if (chartInstance) chartInstance.destroy();
chartInstance = new Chart(ctx, {
type: 'bar',
data: {
labels: ['周一', '周二', '周三', '周四', '周五', '周六'],
datasets: [{
label: '每日加班时长 (小时)',
data: data,
backgroundColor: 'rgba(33, 150, 243, 0.8)',
borderColor: 'rgba(33, 150, 243, 1)',
borderWidth: 2,
borderRadius: 5
}]
},
options: {
responsive: true,
plugins: {
legend: { position: 'top' },
tooltip: { enabled: true }
},
scales: {
y: {
beginAtZero: true,
grid: { color: '#eee' },
ticks: {
callback: v => v + ' 小时',
stepSize: 1
}
},
x: { grid: { display: false } }
},
animation: { duration: 1000 }
}
});
};
// 显示总时长
const showTotal = data => {
const total = data.reduce((a, b) => a + b, 0).toFixed(1);
document.getElementById('total-overtime').innerHTML = `
<div style="background: #e3f2fd; padding: 15px; border-radius: 10px">
📅 本周累计加班时长:<strong style="color: ${total > 40 ? '#f44336' : '#2196F3'}">${total}</strong> 小时
</div>
`;
};
// 初始化图表
updateChart([0, 0, 0, 0, 0, 0]);
</script>
</body>
</html>
```