v2.0.0 — 日打卡彻底改为周打卡
This commit is contained in:
348
static/app.js
348
static/app.js
@@ -5,13 +5,13 @@
|
||||
/* ================================================================
|
||||
State
|
||||
================================================================ */
|
||||
var calendarStatus = {}; // { "2026-06-01": "pass", ... }
|
||||
var calYear, calMonth; // 日历显示的月份
|
||||
var activePanel = 'daily'; // 当前面板
|
||||
var weekOffset = 0; // 每周评分偏移
|
||||
var lastSavedData = null; // 上次保存快照
|
||||
var lastSavedDate = null; // 上次保存日期
|
||||
var selectedDate = null; // 日历中选中日期
|
||||
var calendarStatus = {}; // { "2026-W30": "pass", ... }
|
||||
var calYear; // 日历显示的年
|
||||
var activePanel = 'daily';
|
||||
var weekOffset = 0;
|
||||
var lastSavedData = null;
|
||||
var lastSavedWeek = null;
|
||||
var selectedWeek = null;
|
||||
|
||||
/* 勤学预设项目 */
|
||||
var PRESET_STUDY_ITEMS = [
|
||||
@@ -51,18 +51,18 @@
|
||||
/* ================================================================
|
||||
API
|
||||
================================================================ */
|
||||
function apiGetCheckin(date, cb) {
|
||||
fetch('/api/checkin?date=' + encodeURIComponent(date))
|
||||
function apiGetCheckin(week, cb) {
|
||||
fetch('/api/checkin?week=' + encodeURIComponent(week))
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(res){ if (res.ok) cb(null, res.data); else cb(res.error); })
|
||||
.catch(function(e){ cb(e.message); });
|
||||
}
|
||||
|
||||
function apiSaveCheckin(date, data, cb) {
|
||||
function apiSaveCheckin(week, data, cb) {
|
||||
fetch('/api/checkin', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({date: date, data: data})
|
||||
body: JSON.stringify({week: week, data: data})
|
||||
})
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(res){ if (res.ok) cb(null); else cb(res.error); })
|
||||
@@ -131,91 +131,69 @@
|
||||
return y + '-' + m + '-' + dd;
|
||||
}
|
||||
|
||||
/** 判断两个日期是否同一天 */
|
||||
function isSameDay(a, b) {
|
||||
return a.getFullYear() === b.getFullYear() &&
|
||||
a.getMonth() === b.getMonth() &&
|
||||
a.getDate() === b.getDate();
|
||||
/** 获取当前周的 YYYY-WW 格式 */
|
||||
function fmtWeek(d) {
|
||||
var jan1 = new Date(d.getFullYear(), 0, 1);
|
||||
var dayOfYear = Math.floor((d - jan1) / 86400000);
|
||||
var week = Math.ceil((dayOfYear + jan1.getDay() + 1) / 7);
|
||||
return d.getFullYear() + '-W' + ('0' + week).slice(-2);
|
||||
}
|
||||
|
||||
/** 切换日历月份 */
|
||||
window.changeCalMonth = function(dir) {
|
||||
calMonth += dir;
|
||||
if (calMonth > 12) { calMonth = 1; calYear++; }
|
||||
if (calMonth < 1) { calMonth = 12; calYear--; }
|
||||
/** 切换日历年 */
|
||||
window.changeCalYear = function(dir) {
|
||||
calYear += dir;
|
||||
renderCalendar();
|
||||
};
|
||||
|
||||
/** 渲染日历 */
|
||||
/** 渲染周历 */
|
||||
function renderCalendar() {
|
||||
var today = new Date();
|
||||
var firstDay = new Date(calYear, calMonth - 1, 1);
|
||||
var lastDay = new Date(calYear, calMonth, 0);
|
||||
var startDayOfWeek = firstDay.getDay(); // 0=Sun
|
||||
var totalDays = lastDay.getDate();
|
||||
var prevMonthLastDay = new Date(calYear, calMonth - 1, 0).getDate();
|
||||
|
||||
// 月份标签
|
||||
document.getElementById('cal-month-label').textContent =
|
||||
calYear + '年 ' + calMonth + '月';
|
||||
|
||||
var grid = document.getElementById('cal-grid');
|
||||
document.getElementById('cal-year-label').textContent = calYear + '年';
|
||||
var yearStart = new Date(calYear, 0, 1);
|
||||
var yearEnd = new Date(calYear, 11, 31);
|
||||
var weeks = [];
|
||||
var d = new Date(yearStart);
|
||||
// 推进到第一个周一
|
||||
d.setDate(d.getDate() - d.getDay() + (d.getDay() === 0 ? -6 : 1));
|
||||
while (d <= yearEnd) {
|
||||
var wk = fmtWeek(d);
|
||||
weeks.push(wk);
|
||||
d.setDate(d.getDate() + 7);
|
||||
}
|
||||
var todayWk = fmtWeek(new Date());
|
||||
var el = document.getElementById('cal-week-list');
|
||||
var html = '';
|
||||
|
||||
// 前月填充
|
||||
for (var p = startDayOfWeek - 1; p >= 0; p--) {
|
||||
html += '<div class="cal-cell other-month">' + (prevMonthLastDay - p) + '</div>';
|
||||
for (var i = 0; i < weeks.length; i++) {
|
||||
var w = weeks[i];
|
||||
var cls = 'cal-week-cell';
|
||||
var status = calendarStatus[w];
|
||||
if (status) cls += ' ' + status;
|
||||
if (w === todayWk) cls += ' today';
|
||||
if (w === selectedWeek) cls += ' selected';
|
||||
html += '<div class="' + cls + '" data-week="' + w + '" title="' + w + '">' +
|
||||
'W' + w.split('-W')[1] + '</div>';
|
||||
}
|
||||
|
||||
// 当月
|
||||
for (var d = 1; d <= totalDays; d++) {
|
||||
var cur = new Date(calYear, calMonth - 1, d);
|
||||
var ds = fmtDate(cur);
|
||||
var classes = ['cal-cell'];
|
||||
var isOtherMonth = false;
|
||||
|
||||
if (isSameDay(cur, today)) classes.push('today');
|
||||
if (ds === selectedDate) classes.push('selected');
|
||||
var status = calendarStatus[ds];
|
||||
if (status) classes.push(status);
|
||||
|
||||
html += '<div class="' + classes.join(' ') + '" data-date="' + ds + '">' + d + '</div>';
|
||||
}
|
||||
|
||||
// 后月填充 — 始终 42 格(6行 × 7列),保持高度一致
|
||||
var totalCells = startDayOfWeek + totalDays;
|
||||
var remaining = 42 - totalCells;
|
||||
for (var n = 1; n <= remaining; n++) {
|
||||
html += '<div class="cal-cell other-month">' + n + '</div>';
|
||||
}
|
||||
|
||||
grid.innerHTML = html;
|
||||
|
||||
// 点击事件
|
||||
grid.querySelectorAll('.cal-cell:not(.other-month)').forEach(function(cell) {
|
||||
el.innerHTML = html;
|
||||
el.querySelectorAll('.cal-week-cell').forEach(function(cell) {
|
||||
cell.addEventListener('click', function() {
|
||||
var date = this.dataset.date;
|
||||
if (date) navigateToDate(date);
|
||||
var wk = this.dataset.week;
|
||||
if (wk) navigateToWeek(wk);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** 导航到指定日期 */
|
||||
function navigateToDate(date) {
|
||||
selectedDate = date;
|
||||
function navigateToWeek(week) {
|
||||
selectedWeek = week;
|
||||
switchPanel('daily');
|
||||
document.getElementById('check-date').value = date;
|
||||
document.getElementById('check-date').value = week;
|
||||
loadCheckin();
|
||||
renderCalendar(); // 刷新日历高亮
|
||||
renderCalendar();
|
||||
}
|
||||
|
||||
/** 回到今天 */
|
||||
window.goToday = function() {
|
||||
var today = fmtDate(new Date());
|
||||
window.goToCurrentWeek = function() {
|
||||
var now = fmtWeek(new Date());
|
||||
calYear = new Date().getFullYear();
|
||||
calMonth = new Date().getMonth() + 1;
|
||||
renderCalendar();
|
||||
navigateToDate(today);
|
||||
navigateToWeek(now);
|
||||
};
|
||||
|
||||
/* ================================================================
|
||||
@@ -224,7 +202,7 @@
|
||||
function loadStats() {
|
||||
apiGetStats(function(err, data) {
|
||||
if (!err && data) {
|
||||
document.getElementById('stat-days').textContent = data.total_days;
|
||||
document.getElementById('stat-days').textContent = data.total_weeks;
|
||||
document.getElementById('stat-morning').textContent = data.total_morning;
|
||||
document.getElementById('stat-study').textContent = data.total_study;
|
||||
calendarStatus = data.calendar || {};
|
||||
@@ -318,7 +296,7 @@
|
||||
var div = document.createElement('div');
|
||||
div.className = 'item-row';
|
||||
div.innerHTML = '<span class="idx">' + (idx+1) + '.</span>' +
|
||||
'<input type="text" value="' + esc(text) + '" placeholder="今天最重要的一件事…">' +
|
||||
'<input type="text" value="' + esc(text) + '" placeholder="本周最重要的一件事…">' +
|
||||
'<button class="btn-del" onclick="this.parentElement.remove();renumberMorning()"><svg class="icon-sm"><use href="#icon-x"/></svg></button>';
|
||||
container.appendChild(div);
|
||||
renumberMorning();
|
||||
@@ -410,7 +388,7 @@
|
||||
var totalDays = data.length;
|
||||
var totalEvents = 0;
|
||||
data.forEach(function(d){ totalEvents += d.events.length; });
|
||||
summary.innerHTML = '同步完成!共 <b>' + totalDays + '</b> 天有日程,合计 <b>' + totalEvents + '</b> 个会议' + (res.saved_days ? ',已自动填充 <b>' + res.saved_days + '</b> 天' : '');
|
||||
summary.innerHTML = '同步完成!共 <b>' + totalDays + '</b> 周有日程,合计 <b>' + totalEvents + '</b> 个会议' + (res.saved_days ? ',已自动填充 <b>' + res.saved_days + '</b> 周' : '');
|
||||
|
||||
// 渲染结果列表
|
||||
var html = '';
|
||||
@@ -428,8 +406,8 @@
|
||||
});
|
||||
list.innerHTML = html;
|
||||
|
||||
// 自动填充今天到选中日期的日程
|
||||
autoFillTodayEvents(data);
|
||||
// 刷新当前页
|
||||
loadCheckin();
|
||||
})
|
||||
.catch(function(){
|
||||
loading.style.display = 'none';
|
||||
@@ -439,30 +417,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
function autoFillTodayEvents(data) {
|
||||
var todayDate = document.getElementById('check-date').value;
|
||||
var added = 0;
|
||||
data.forEach(function(day) {
|
||||
if (day.date !== todayDate) return;
|
||||
day.events.forEach(function(e) {
|
||||
var text = e.time ? '【' + e.time + '】' + e.summary : e.summary;
|
||||
if (e.location) text += ' @' + e.location;
|
||||
var existing = document.querySelectorAll('#morning-list input[type="text"]');
|
||||
var already = false;
|
||||
existing.forEach(function(inp){ if (inp.value.indexOf(e.summary) >= 0) already = true; });
|
||||
if (already) return;
|
||||
var count = document.querySelectorAll('#morning-list .item-row').length;
|
||||
if (count >= 3) return;
|
||||
addMorningRow(text);
|
||||
added++;
|
||||
});
|
||||
});
|
||||
if (added > 0) {
|
||||
showToast('已自动填充 ' + added + ' 条今日日程', 'info');
|
||||
triggerAutoSave();
|
||||
}
|
||||
}
|
||||
|
||||
window.closeSyncModal = function() {
|
||||
var overlay = document.getElementById('sync-modal-overlay');
|
||||
if (overlay) overlay.style.display = 'none';
|
||||
@@ -492,24 +446,22 @@
|
||||
================================================================ */
|
||||
|
||||
window.loadCheckin = function() {
|
||||
var date = document.getElementById('check-date').value;
|
||||
if (!date) return;
|
||||
var week = document.getElementById('check-date').value;
|
||||
if (!week) return;
|
||||
|
||||
// 切换日期前先保存当前数据
|
||||
var currentData = buildData();
|
||||
var currentStr = JSON.stringify(currentData);
|
||||
if (lastSavedDate && lastSavedData !== null && currentStr !== lastSavedData) {
|
||||
// 有未保存的变更,先静默保存
|
||||
if (lastSavedWeek && lastSavedData !== null && currentStr !== lastSavedData) {
|
||||
var hasContent = currentData.morning.some(function(x){return x && x.trim();}) ||
|
||||
currentData.evening.some(function(x){return (x.mistake||'').trim() || (x.improvement||'').trim();}) ||
|
||||
currentData.study.some(function(x){return x.done;});
|
||||
if (hasContent) {
|
||||
apiSaveCheckin(lastSavedDate, currentData, function(){}); // 静默保存
|
||||
apiSaveCheckin(lastSavedWeek, currentData, function(){});
|
||||
}
|
||||
}
|
||||
|
||||
lastSavedDate = date;
|
||||
apiGetCheckin(date, function(err, row){
|
||||
lastSavedWeek = week;
|
||||
apiGetCheckin(week, function(err, row){
|
||||
if (err) { initStudyPresets(); lastSavedData = '{}'; return; }
|
||||
fillForm(row ? row.data : null);
|
||||
lastSavedData = JSON.stringify(buildData());
|
||||
@@ -518,26 +470,26 @@
|
||||
|
||||
/** 自动保存 — 失去焦点/勾选/删除时触发 */
|
||||
function triggerAutoSave() {
|
||||
var date = document.getElementById('check-date').value;
|
||||
if (!date) return;
|
||||
var week = document.getElementById('check-date').value;
|
||||
if (!week) return;
|
||||
var data = buildData();
|
||||
var dataStr = JSON.stringify(data);
|
||||
if (dataStr === lastSavedData) return;
|
||||
apiSaveCheckin(date, data, function(err){
|
||||
apiSaveCheckin(week, data, function(err){
|
||||
if (err) { showToast('保存失败', 'error'); return; }
|
||||
lastSavedData = dataStr;
|
||||
loadStats();
|
||||
});
|
||||
}
|
||||
|
||||
/** 为每日打卡面板绑定自动保存事件 */
|
||||
/** 为每周打卡面板绑定自动保存事件 */
|
||||
function bindAutoSave() {
|
||||
var panel = document.getElementById('panel-daily');
|
||||
if (!panel) return;
|
||||
|
||||
// 输入框 & 文本域 & 下拉选择器:失去焦点时保存
|
||||
panel.addEventListener('blur', function(e) {
|
||||
if (e.target.matches('input[type="text"], textarea, input[type="date"], select')) {
|
||||
if (e.target.matches('input[type="text"], textarea, input[type="week"], select')) {
|
||||
triggerAutoSave();
|
||||
}
|
||||
}, true);
|
||||
@@ -586,97 +538,70 @@
|
||||
function loadWeekly() {
|
||||
var today = new Date();
|
||||
today.setDate(today.getDate() + weekOffset * 7);
|
||||
var monday = getMonday(today);
|
||||
var sunday = new Date(monday);
|
||||
sunday.setDate(monday.getDate() + 6);
|
||||
var wk = fmtWeek(today);
|
||||
document.getElementById('week-label').textContent = wk;
|
||||
|
||||
document.getElementById('week-label').textContent =
|
||||
fmtDate(monday) + ' ~ ' + fmtDate(sunday);
|
||||
|
||||
apiGetHistory(function(err, rows){
|
||||
apiGetCheckin(wk, function(err, row){
|
||||
if (err) { showToast('加载失败', 'error'); return; }
|
||||
var map = {};
|
||||
for (var i=0; i<rows.length; i++) map[rows[i].date] = rows[i].data;
|
||||
|
||||
var totalDays = 0, totalScore = 0, dayCells = [];
|
||||
|
||||
for (var j=0; j<7; j++) {
|
||||
var cur = new Date(monday);
|
||||
cur.setDate(monday.getDate() + j);
|
||||
var ds = fmtDate(cur);
|
||||
var dd = map[ds];
|
||||
|
||||
if (dd) {
|
||||
totalDays++;
|
||||
var morning = dd.morning || [];
|
||||
var evening = dd.evening || [];
|
||||
var study = dd.study || [];
|
||||
|
||||
var morningCount = morning.filter(function(x){ return x && typeof x === 'string' && x.trim(); }).length;
|
||||
var eveningCount = evening.filter(function(x){
|
||||
var mst = typeof x === 'string' ? x : (x.mistake || '');
|
||||
return mst && typeof mst === 'string' && mst.trim();
|
||||
}).length;
|
||||
var studyCount = study.filter(function(x){ return x.done; }).length;
|
||||
|
||||
var allThree = morningCount > 0 && eveningCount > 0 && studyCount > 0;
|
||||
var dayScore, status;
|
||||
if (allThree) {
|
||||
dayScore = 60 + (morningCount - 1 + eveningCount - 1 + studyCount - 1) * 5;
|
||||
status = 'pass';
|
||||
} else {
|
||||
dayScore = (morningCount + eveningCount + studyCount) * 5;
|
||||
status = 'fail';
|
||||
}
|
||||
totalScore += dayScore;
|
||||
|
||||
dayCells.push({
|
||||
ds: ds, dayScore: dayScore, status: status,
|
||||
weekday: '周' + WEEKDAYS_CN[cur.getDay()]
|
||||
});
|
||||
} else {
|
||||
dayCells.push({
|
||||
ds: ds, dayScore: 0, status: 'empty',
|
||||
weekday: '周' + WEEKDAYS_CN[cur.getDay()]
|
||||
});
|
||||
}
|
||||
var dd = row ? row.data : null;
|
||||
if (!dd) {
|
||||
document.getElementById('weekly-score').textContent = '--';
|
||||
document.getElementById('score-text').textContent = '本周暂无记录';
|
||||
document.getElementById('score-stats').textContent = '';
|
||||
document.getElementById('week-days-grid').innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
var score = totalScore;
|
||||
var morning = dd.morning || [];
|
||||
var evening = dd.evening || [];
|
||||
var study = dd.study || [];
|
||||
|
||||
var morningCount = morning.filter(function(x){ return x && typeof x === 'string' && x.trim(); }).length;
|
||||
if (!morningCount) {
|
||||
morningCount = morning.filter(function(x){
|
||||
return x && typeof x === 'object' && (x.text || '').trim();
|
||||
}).length;
|
||||
}
|
||||
var eveningCount = evening.filter(function(x){
|
||||
var mst = typeof x === 'string' ? x : (x.mistake || '');
|
||||
return mst && typeof mst === 'string' && mst.trim();
|
||||
}).length;
|
||||
var studyCount = study.filter(function(x){ return x.done; }).length;
|
||||
|
||||
var allThree = morningCount > 0 && eveningCount > 0 && studyCount > 0;
|
||||
var score, status;
|
||||
if (allThree) {
|
||||
score = 60 + (morningCount - 1) * 5 + (eveningCount - 1) * 3 + studyCount * 3;
|
||||
status = 'pass';
|
||||
} else {
|
||||
score = 0;
|
||||
status = 'fail';
|
||||
}
|
||||
|
||||
var grade = score >= 90 ? '优秀' : score >= 75 ? '良好' : score >= 60 ? '达标' : '未达标';
|
||||
|
||||
document.getElementById('weekly-score').textContent = score;
|
||||
|
||||
var ring = document.querySelector('.score-ring');
|
||||
if (ring) {
|
||||
var R = 50, C = 2 * Math.PI * R;
|
||||
ring.setAttribute('stroke-dasharray', C);
|
||||
ring.setAttribute('stroke-dashoffset', C - (C * totalDays / 7));
|
||||
var ratio = Math.min(score / 100, 1);
|
||||
ring.setAttribute('stroke-dashoffset', C - (C * ratio));
|
||||
}
|
||||
|
||||
var txt = '';
|
||||
if (totalDays >= 7) txt = '全勤!本周每天都有记录';
|
||||
else if (totalDays >= 5) txt = '良好,保持了大部分记录';
|
||||
else if (totalDays >= 3) txt = '一般,需要更规律打卡';
|
||||
else txt = '本周记录偏少,加油!';
|
||||
var txt = grade + ' · ' + score + ' 分';
|
||||
document.getElementById('score-text').textContent = txt;
|
||||
|
||||
var completedDays = dayCells.filter(function(c){ return c.status === 'pass'; }).length;
|
||||
var totalFilled = dayCells.filter(function(c){ return c.status !== 'empty'; }).length;
|
||||
document.getElementById('score-stats').textContent =
|
||||
'本周填卡 ' + totalFilled + '/7 天 · 达标 ' + completedDays + ' 天';
|
||||
'立志 ' + morningCount + ' · 责善 ' + eveningCount + ' · 勤学 ' + studyCount + '/8';
|
||||
|
||||
var gridHtml = '';
|
||||
for (var g=0; g<dayCells.length; g++) {
|
||||
var cell = dayCells[g];
|
||||
var dateParts = cell.ds.split('-');
|
||||
var shortDate = dateParts[1] + '/' + dateParts[2];
|
||||
var badgeText = cell.status === 'pass' ? '达标' : (cell.status === 'fail' ? '未达标' : '未打卡');
|
||||
gridHtml += '<div class="day-cell ' + cell.status + '">' +
|
||||
'<div class="day-label">' + cell.weekday + '</div>' +
|
||||
'<div class="day-date">' + shortDate + '</div>' +
|
||||
'<div class="day-score">' + cell.dayScore + '<span style="font-size:11px;font-weight:400">分</span></div>' +
|
||||
'<div class="day-badge">' + badgeText + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
// 渲染周统计网格(简化版)
|
||||
var gridHtml = '<div class="day-cell ' + status + '">' +
|
||||
'<div class="day-label">' + wk + '</div>' +
|
||||
'<div class="day-date">' + grade + '</div>' +
|
||||
'<div class="day-score">' + score + '<span style="font-size:11px;font-weight:400">分</span></div>' +
|
||||
'<div class="day-badge">' + (status === 'pass' ? '达标' : '未达标') + '</div>' +
|
||||
'</div>';
|
||||
document.getElementById('week-days-grid').innerHTML = gridHtml;
|
||||
});
|
||||
}
|
||||
@@ -699,7 +624,9 @@
|
||||
var html = '';
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
var r = rows[i];
|
||||
var morning = (r.data.morning || []).filter(function(x){ return x && typeof x === 'string' && x.trim(); });
|
||||
var morning = (r.data.morning || []).filter(function(x){
|
||||
return (typeof x === 'string' && x.trim()) || (typeof x === 'object' && (x.text||'').trim());
|
||||
});
|
||||
var evening = (r.data.evening || []).filter(function(x){
|
||||
var mst = typeof x === 'string' ? x : (x.mistake || '');
|
||||
return mst && typeof mst === 'string' && mst.trim();
|
||||
@@ -707,9 +634,9 @@
|
||||
var study = (r.data.study || []).filter(function(x){ return x.done; });
|
||||
|
||||
var tags = [];
|
||||
if (morning.length) tags.push('<span><svg class="icon-xs" style="color:var(--primary)"><use href="#icon-sun"/></svg> 立志 ' + morning.length + '</span>');
|
||||
if (evening.length) tags.push('<span><svg class="icon-xs" style="color:var(--danger)"><use href="#icon-magnifying-glass"/></svg> 改过 ' + evening.length + '</span>');
|
||||
if (study.length) tags.push('<span><svg class="icon-xs" style="color:#059669"><use href="#icon-book-open"/></svg> 勤学 ' + study.length + '</span>');
|
||||
if (morning.length) tags.push('<span><svg class="icon-xs" style="color:var(--primary)"><use href="#icon-sun"/></svg> ' + morning.length + '</span>');
|
||||
if (evening.length) tags.push('<span><svg class="icon-xs" style="color:var(--danger)"><use href="#icon-magnifying-glass"/></svg> ' + evening.length + '</span>');
|
||||
if (study.length) tags.push('<span><svg class="icon-xs" style="color:#059669"><use href="#icon-book-open"/></svg> ' + study.length + '/8</span>');
|
||||
|
||||
html += '<div class="history-card">' +
|
||||
'<div class="info">' +
|
||||
@@ -723,13 +650,13 @@
|
||||
});
|
||||
}
|
||||
|
||||
window.deleteHistory = function(date) {
|
||||
if (!confirm('确定删除 ' + date + ' 的打卡记录吗?此操作不可恢复!')) return;
|
||||
apiDeleteCheckin(date, function(err){
|
||||
window.deleteHistory = function(week) {
|
||||
if (!confirm('确定删除 ' + week + ' 的打卡记录吗?此操作不可恢复!')) return;
|
||||
apiDeleteCheckin(week, function(err){
|
||||
if (err) { showToast('删除失败: ' + err, 'error'); return; }
|
||||
showToast('已删除', 'info');
|
||||
loadHistory();
|
||||
loadStats(); // 更新统计
|
||||
loadStats();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1091,29 +1018,28 @@
|
||||
function init() {
|
||||
var today = new Date();
|
||||
calYear = today.getFullYear();
|
||||
calMonth = today.getMonth() + 1;
|
||||
|
||||
var cd = document.getElementById('check-date');
|
||||
var todayStr = fmtDate(today);
|
||||
if (cd) cd.value = todayStr;
|
||||
var todayWk = fmtWeek(today);
|
||||
if (cd) cd.value = todayWk;
|
||||
|
||||
selectedDate = todayStr;
|
||||
selectedWeek = todayWk;
|
||||
initStudyPresets();
|
||||
bindAutoSave();
|
||||
lastSavedDate = todayStr;
|
||||
lastSavedWeek = todayWk;
|
||||
|
||||
// 从页面嵌入数据获取初始统计(0 延迟)
|
||||
if (window.__INITIAL_STATS__) {
|
||||
var s = window.__INITIAL_STATS__;
|
||||
document.getElementById('stat-days').textContent = s.total_days;
|
||||
document.getElementById('stat-days').textContent = s.total_weeks;
|
||||
document.getElementById('stat-morning').textContent = s.total_morning;
|
||||
document.getElementById('stat-study').textContent = s.total_study;
|
||||
calendarStatus = s.calendar || {};
|
||||
}
|
||||
|
||||
loadCheckin();
|
||||
loadStats(); // 异步刷新最新数据
|
||||
renderCalendar(); // 同步渲染 — calendarStatus 已有值
|
||||
loadStats();
|
||||
renderCalendar();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
Reference in New Issue
Block a user