You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

打卡应用开发:基于localStorage持久存储时间戳并按日期层级展示

Solution for Persistent Check-In Records with Date Ordering

Hey there! Let's get your check-in app sorted to store records permanently in localStorage and display newer daily records below older ones. First, let's break down the issues with the current code:

  • Right now, you're overwriting a single completeDate value in localStorage instead of storing a collection of daily check-in groups.
  • There's no logic to load and display historical records when the page loads.
  • The check-in times aren't grouped by their respective dates.

Here's the revised implementation that fixes all these points:

Full Updated Code

HTML

<button id="checkInBtn">Marcar</button> 
<div id="markTimes"></div>

JavaScript

// Initialize or load existing check-in records from localStorage
let checkInRecords = JSON.parse(localStorage.getItem('checkInRecords')) || [];

// Helper function to get current date in YYYY-MM-DD format (for grouping records)
function getCurrentDateString() {
  const date = new Date();
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
}

// Helper function to format time as HH:MM:SS
function formatTime(date) {
  return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`;
}

// Render all check-in records to the DOM
function renderRecords() {
  const container = document.getElementById('markTimes');
  container.innerHTML = ''; // Clear existing content first

  // Render records in order: oldest first, newest last (so next day's records show below previous)
  checkInRecords.forEach(record => {
    // Create a date header
    const dateHeader = document.createElement('div');
    dateHeader.textContent = `Check-ins for ${record.date}`;
    dateHeader.style.marginTop = '1rem';
    dateHeader.style.fontWeight = 'bold';
    container.appendChild(dateHeader);

    // Create time elements for each check-in
    record.times.forEach(time => {
      const timeSpan = document.createElement('span');
      timeSpan.className = 'dataTime';
      timeSpan.style.marginRight = '1rem';
      timeSpan.textContent = time;
      container.appendChild(timeSpan);
    });
  });

  // Update button state based on today's record
  updateButtonState();
}

// Update button enabled/disabled state based on today's check-in count
function updateButtonState() {
  const btn = document.getElementById('checkInBtn');
  const todayDate = getCurrentDateString();
  const todayRecord = checkInRecords.find(record => record.date === todayDate);
  
  // Disable button if today's record has 4 check-ins, else enable
  btn.disabled = todayRecord?.times.length >= 4;
}

// Handle check-in button click
function getTime() {
  const todayDate = getCurrentDateString();
  const currentTime = formatTime(new Date());
  
  // Find today's record, or create a new one if it doesn't exist
  let todayRecord = checkInRecords.find(record => record.date === todayDate);
  if (!todayRecord) {
    todayRecord = { date: todayDate, times: [] };
    checkInRecords.push(todayRecord);
  }

  // Only add the time if we haven't reached 4 check-ins today
  if (todayRecord.times.length < 4) {
    todayRecord.times.push(currentTime);
    // Save updated records to localStorage
    localStorage.setItem('checkInRecords', JSON.stringify(checkInRecords));
    // Re-render the records to update the UI
    renderRecords();

    // If we just added the 4th check-in, disable the button immediately
    if (todayRecord.times.length === 4) {
      document.getElementById('checkInBtn').disabled = true;
    } else {
      // Optional: Re-enable button after 3 seconds if not maxed out (keeping your original logic)
      setTimeout(() => {
        document.getElementById('checkInBtn').disabled = false;
      }, 3000);
    }
  }
}

// Set up button click listener (better practice than inline onclick)
document.getElementById('checkInBtn').addEventListener('click', getTime);

// Render existing records when the page loads
window.addEventListener('load', renderRecords);

Key Improvements Explained

  • Date-based grouping: Records are stored as an array of objects, each tied to a specific date (YYYY-MM-DD format), so we can easily track daily check-ins without overwriting data.
  • Persistent storage: The entire checkInRecords array is saved to localStorage whenever a check-in is added, ensuring all historical data is retained.
  • Proper UI rendering: When the page loads, all past records are rendered automatically, with older dates appearing above newer ones (so next day's records show below previous days).
  • Better button state management: The button's enabled/disabled state is updated based on today's check-in count, both on page load and after each click.
  • Cleaner code structure: Split logic into helper functions for date formatting, rendering, and button state, making the code easier to maintain.

内容的提问来源于stack exchange,提问作者josecarlos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:32:43