duidui_mini_program/pages/camp_task_objective_questions/modules/timer-service.js
2026-03-27 10:41:46 +08:00

165 lines
3.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 计时器服务模块
* 负责答题计时相关逻辑
*/
/**
* 格式化时间显示(秒数转为 HH:MM:SS 格式)
* @param {Number} totalSeconds - 总秒数
* @returns {String} 格式化后的时间字符串
*/
export function formatTime(totalSeconds) {
if (totalSeconds < 0) totalSeconds = 0;
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
const formatNumber = (num) => {
return num < 10 ? '0' + num : String(num);
};
if (hours > 0) {
return `${formatNumber(hours)}:${formatNumber(minutes)}:${formatNumber(seconds)}`;
} else {
return `${formatNumber(minutes)}:${formatNumber(seconds)}`;
}
}
/**
* 启动计时器
* @param {Object} context - 页面上下文
* @param {Number} durationMinutes - 考试时长(分钟)
* @param {String} startTime - 开始时间ISO 字符串)
* @param {Function} onTimeUp - 时间到回调
* @returns {Number} 定时器ID
*/
export function startTimer(context, durationMinutes, startTime, onTimeUp) {
if (context.timerInterval) {
clearInterval(context.timerInterval);
}
const startTimestamp = new Date(startTime).getTime();
const durationMs = durationMinutes * 60 * 1000;
const endTimestamp = startTimestamp + durationMs;
const updateTimer = () => {
const now = Date.now();
const remainingMs = Math.max(0, endTimestamp - now);
const remainingSeconds = Math.floor(remainingMs / 1000);
if (remainingSeconds <= 0) {
clearInterval(context.timerInterval);
context.timerInterval = null;
context.setData({
timerText: '00:00',
isPaused: false
});
if (onTimeUp) {
onTimeUp();
}
return;
}
context.setData({
timerText: formatTime(remainingSeconds)
});
};
updateTimer();
context.timerInterval = setInterval(updateTimer, 1000);
return context.timerInterval;
}
/**
* 暂停计时器
* @param {Object} context - 页面上下文
* @returns {Number} 暂停时的剩余秒数
*/
export function pauseTimer(context) {
if (context.timerInterval) {
clearInterval(context.timerInterval);
context.timerInterval = null;
}
const timerText = context.data.timerText || '00:00:00';
const parts = timerText.split(':');
let totalSeconds = 0;
if (parts.length === 3) {
totalSeconds = parseInt(parts[0]) * 3600 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
} else if (parts.length === 2) {
totalSeconds = parseInt(parts[0]) * 60 + parseInt(parts[1]);
}
context.setData({
isPaused: true,
pauseStartTime: Date.now()
});
return totalSeconds;
}
/**
* 恢复计时器
* @param {Object} context - 页面上下文
* @param {Number} pausedSeconds - 暂停时的剩余秒数
* @param {Function} onTimeUp - 时间到回调
*/
export function resumeTimer(context, pausedSeconds, onTimeUp) {
if (context.timerInterval) {
clearInterval(context.timerInterval);
}
const pauseDuration = context.data.pauseStartTime ? Math.floor((Date.now() - context.data.pauseStartTime) / 1000) : 0;
const remainingSeconds = Math.max(0, pausedSeconds - pauseDuration);
if (remainingSeconds <= 0) {
context.setData({
timerText: '00:00',
isPaused: false
});
if (onTimeUp) {
onTimeUp();
}
return;
}
context.setData({
isPaused: false,
pauseStartTime: null
});
let currentSeconds = remainingSeconds;
context.timerInterval = setInterval(() => {
currentSeconds--;
if (currentSeconds <= 0) {
clearInterval(context.timerInterval);
context.timerInterval = null;
context.setData({
timerText: '00:00',
isPaused: false
});
if (onTimeUp) {
onTimeUp();
}
return;
}
context.setData({
timerText: formatTime(currentSeconds)
});
}, 1000);
}
/**
* 停止计时器
* @param {Object} context - 页面上下文
*/
export function stopTimer(context) {
if (context.timerInterval) {
clearInterval(context.timerInterval);
context.timerInterval = null;
}
}