553 lines
23 KiB
HTML
553 lines
23 KiB
HTML
<!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:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;background:linear-gradient(135deg,#1a1a2e 0%,#16213e 50%,#0f3460 100%);min-height:100vh;padding:20px}
|
||
.container{max-width:800px;margin:0 auto;background:#fff;border-radius:20px;box-shadow:0 20px 60px rgba(0,0,0,.4);overflow:hidden}
|
||
.header{background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:#fff;padding:24px 30px 30px;text-align:center}
|
||
.header h1{font-size:28px;margin-bottom:6px}
|
||
.header .motto{font-size:13px;opacity:.85}
|
||
.js-badge{display:inline-block;background:rgba(255,255,255,.2);padding:3px 10px;border-radius:10px;font-size:11px;margin-top:8px}
|
||
|
||
.tabs{display:flex;border-bottom:2px solid #e0e0e0}
|
||
.tab{flex:1;padding:14px;text-align:center;cursor:pointer;background:#f8f9fa;border:none;font-size:15px;color:#666;transition:all .2s}
|
||
.tab:hover{background:#eef0ff}
|
||
.tab.active{background:#fff;color:#667eea;font-weight:bold;border-bottom:3px solid #667eea}
|
||
.tab-content{display:none;padding:20px}
|
||
.tab-content.active{display:block}
|
||
|
||
.date-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:0 0 16px}
|
||
.date-row input[type="date"]{padding:10px 14px;border:2px solid #ddd;border-radius:8px;font-size:14px;flex:1;min-width:140px}
|
||
.date-row button{padding:10px 18px;border:none;border-radius:8px;cursor:pointer;font-size:14px;white-space:nowrap;font-weight:500}
|
||
.btn-save{background:#667eea;color:#fff}
|
||
.btn-save:hover{background:#5568d3}
|
||
.btn-save:active{transform:scale(.97)}
|
||
.btn-outline{background:#fff;color:#667eea;border:2px solid #667eea!important}
|
||
.btn-outline:hover{background:#eef0ff}
|
||
|
||
/* Section */
|
||
.section{margin-bottom:18px;padding:16px;background:#f6f7fb;border-radius:12px}
|
||
.section h2{font-size:16px;margin-bottom:10px;color:#333;display:flex;align-items:center;gap:8px}
|
||
.section h2 span{font-size:22px}
|
||
.section h2 .hint{font-size:11px;color:#999;margin-left:auto;font-weight:normal}
|
||
|
||
/* 动态条目 */
|
||
.item-row{display:flex;gap:8px;align-items:flex-start;margin-bottom:8px}
|
||
.item-row .item-num{width:24px;height:24px;border-radius:50%;background:#667eea;color:#fff;font-size:11px;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:10px}
|
||
.item-row textarea{flex:1;padding:10px;border:2px solid #e0e0e0;border-radius:8px;font-size:13px;font-family:inherit;resize:vertical;min-height:40px}
|
||
.item-row textarea:focus{outline:none;border-color:#667eea}
|
||
.item-action{display:flex;flex-direction:column;gap:2px}
|
||
.item-action button{width:28px;height:28px;border-radius:6px;border:none;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;transition:all .15s}
|
||
.btn-add{background:#10b981;color:#fff}
|
||
.btn-add:hover{background:#059669}
|
||
.btn-del{background:#ef4444;color:#fff}
|
||
.btn-del:hover{background:#dc2626}
|
||
|
||
/* Check items */
|
||
.check-item{padding:10px 12px;background:#fff;border-radius:8px;border-left:4px solid #667eea;margin-bottom:8px;display:flex;align-items:center;gap:10px}
|
||
.check-item label{flex:1;cursor:pointer;font-size:14px;line-height:1.5;display:flex;align-items:center;gap:10px}
|
||
.check-item input[type="checkbox"]{width:18px;height:18px;cursor:pointer;accent-color:#667eea;flex-shrink:0}
|
||
.check-item .del-btn{width:24px;height:24px;border-radius:6px;border:none;cursor:pointer;font-size:12px;background:#fee2e2;color:#ef4444;flex-shrink:0;display:flex;align-items:center;justify-content:center}
|
||
.check-item .del-btn:hover{background:#fca5a5;color:#dc2626}
|
||
|
||
.add-study-btn{display:flex;align-items:center;gap:6px;padding:8px 14px;border:2px dashed #667eea;border-radius:8px;background:transparent;color:#667eea;cursor:pointer;font-size:13px;margin-top:6px;width:100%;justify-content:center}
|
||
.add-study-btn:hover{background:#eef0ff}
|
||
|
||
.save-btn{display:block;width:100%;padding:14px;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:#fff;border:none;border-radius:12px;font-size:16px;cursor:pointer;margin-top:10px;transition:all .2s;font-weight:500}
|
||
.save-btn:hover{opacity:.9}
|
||
.save-btn:active{transform:scale(.98)}
|
||
|
||
/* Toast */
|
||
.toast{position:fixed;top:20px;left:50%;transform:translateX(-50%);padding:12px 28px;border-radius:10px;color:#fff;font-size:14px;z-index:9999;font-weight:500;animation:toastIn .3s ease;box-shadow:0 8px 30px rgba(0,0,0,.2)}
|
||
.toast.success{background:#10b981}
|
||
.toast.error{background:#ef4444}
|
||
.toast.info{background:#667eea}
|
||
@keyframes toastIn{from{opacity:0;transform:translateX(-50%) translateY(-20px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
|
||
|
||
/* Week navigator */
|
||
.week-nav{display:flex;align-items:center;gap:10px;justify-content:center;margin-bottom:16px}
|
||
.week-nav button{width:36px;height:36px;border-radius:50%;border:2px solid #667eea;background:#fff;color:#667eea;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center}
|
||
.week-nav button:hover{background:#667eea;color:#fff}
|
||
.week-nav .week-label{font-size:14px;font-weight:500;color:#333;min-width:160px;text-align:center}
|
||
|
||
/* Score */
|
||
.score-box{text-align:center;padding:30px 20px;background:#f6f7fb;border-radius:12px}
|
||
.score-bar-wrap{height:8px;background:#e5e7eb;border-radius:4px;margin:16px 0;overflow:hidden}
|
||
.score-bar{height:100%;border-radius:4px;background:linear-gradient(90deg,#667eea,#764ba2);transition:width .5s ease}
|
||
.score-num{font-size:64px;font-weight:bold;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||
.score-txt{font-size:16px;color:#666;margin-top:6px}
|
||
.score-detail{text-align:left;font-size:13px;margin-top:16px}
|
||
.score-detail .day-row{display:flex;align-items:center;gap:10px;padding:6px 0;border-bottom:1px solid #eee;font-size:12px}
|
||
|
||
.history-item{padding:14px;border-bottom:1px solid #eee}
|
||
.history-item .date{font-weight:bold;color:#667eea}
|
||
.history-item .note{font-size:12px;color:#888;margin-top:4px;line-height:1.5}
|
||
.empty-state{text-align:center;color:#999;padding:40px;font-size:14px}
|
||
|
||
/* 紧凑标签 */
|
||
.tag{display:inline-block;padding:2px 8px;border-radius:6px;font-size:11px;margin-right:4px}
|
||
.tag.done{background:#d1fae5;color:#065f46}
|
||
.tag.miss{background:#fee2e2;color:#991b1b}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>⚡ 紫微力量</h1>
|
||
<p class="motto">立志不摇 · 责善不滥 · 改过不拖 · 勤学不辍</p>
|
||
<div class="js-badge" id="js-check">⏳ JS 加载中...</div>
|
||
</div>
|
||
|
||
<div class="tabs">
|
||
<button class="tab active" onclick="switchTab('daily',event)">📅 每日打卡</button>
|
||
<button class="tab" onclick="switchTab('weekly',event)">📊 每周评分</button>
|
||
<button class="tab" onclick="switchTab('history',event)">📜 历史记录</button>
|
||
</div>
|
||
|
||
<!-- ========== 每日打卡 ========== -->
|
||
<div id="daily-tab" class="tab-content active">
|
||
<div class="date-row">
|
||
<input type="date" id="check-date" onchange="loadChecklist()">
|
||
<button class="btn-save" onclick="saveChecklist()">💾 保存</button>
|
||
</div>
|
||
|
||
<!-- 早间立志:最多3条 -->
|
||
<div class="section">
|
||
<h2><span>🌅</span> 早间立志 <span class="hint">今日最重要的事(最多3条)</span></h2>
|
||
<div id="morning-items"><!-- 动态生成 --></div>
|
||
<button class="add-study-btn" onclick="addMorningItem()" id="add-morning-btn">+ 增加一条</button>
|
||
</div>
|
||
|
||
<!-- 责善·改过:最多5条 -->
|
||
<div class="section">
|
||
<h2><span>⚖️</span> 责善·改过 <span class="hint">今日反思(最多5条)</span></h2>
|
||
<div id="review-items"><!-- 动态生成 --></div>
|
||
<button class="add-study-btn" onclick="addReviewItem()" id="add-review-btn">+ 增加一条</button>
|
||
</div>
|
||
|
||
<!-- 勤学打卡:动态增加 -->
|
||
<div class="section">
|
||
<h2><span>📚</span> 勤学打卡 <span class="hint">可自由增减</span></h2>
|
||
<div id="study-items"><!-- 动态生成 --></div>
|
||
<button class="add-study-btn" onclick="addStudyItem()" id="add-study-btn">+ 增加项目</button>
|
||
</div>
|
||
|
||
<button class="save-btn" onclick="saveChecklist()">💾 保存今日打卡</button>
|
||
</div>
|
||
|
||
<!-- ========== 每周评分 ========== -->
|
||
<div id="weekly-tab" class="tab-content">
|
||
<div class="week-nav">
|
||
<button onclick="prevWeek()">◀</button>
|
||
<div class="week-label" id="week-label">本周</div>
|
||
<button onclick="nextWeek()">▶</button>
|
||
</div>
|
||
<button class="btn-outline" style="width:100%;margin-bottom:16px" onclick="goThisWeek()">📍 回到本周</button>
|
||
<div class="score-box">
|
||
<div class="score-num" id="weekly-score">--</div>
|
||
<div class="score-bar-wrap"><div class="score-bar" id="score-bar" style="width:0%"></div></div>
|
||
<div class="score-txt" id="score-text">选择一周查看评分</div>
|
||
<div class="score-detail" id="weekly-details"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ========== 历史记录 ========== -->
|
||
<div id="history-tab" class="tab-content">
|
||
<h2 style="font-size:17px;margin-bottom:16px;display:flex;align-items:center;gap:8px">📜 打卡历史</h2>
|
||
<div id="history-list"><div class="empty-state">暂无打卡记录</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
'use strict';
|
||
|
||
document.getElementById('js-check').textContent = '✅ JS 已就绪';
|
||
document.getElementById('js-check').style.background = 'rgba(16,185,129,.3)';
|
||
|
||
var STORAGE_KEY = 'ziwei_power_data';
|
||
var WEEK_OFFSET = 0; // 周评分偏移量(0=本周,-1=上周,1=下周)
|
||
|
||
// ========== Toast ==========
|
||
function showToast(msg, type) {
|
||
var t = document.createElement('div');
|
||
t.className = 'toast ' + (type || 'info');
|
||
t.textContent = msg;
|
||
document.body.appendChild(t);
|
||
setTimeout(function(){ t.remove(); }, 2500);
|
||
}
|
||
|
||
// ========== 数据 ==========
|
||
function getData() {
|
||
try { var r = localStorage.getItem(STORAGE_KEY); return r ? JSON.parse(r) : {}; }
|
||
catch(e) { return {}; }
|
||
}
|
||
function saveData(d) {
|
||
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(d)); return true; }
|
||
catch(e) { return false; }
|
||
}
|
||
|
||
// ========== Tab ==========
|
||
function switchTab(tabName, ev) {
|
||
var tabs = document.querySelectorAll('.tab');
|
||
var contents = document.querySelectorAll('.tab-content');
|
||
for (var i = 0; i < tabs.length; i++) tabs[i].classList.remove('active');
|
||
for (var j = 0; j < contents.length; j++) contents[j].classList.remove('active');
|
||
if (ev && ev.target) ev.target.classList.add('active');
|
||
var el = document.getElementById(tabName + '-tab');
|
||
if (el) el.classList.add('active');
|
||
if (tabName === 'history') loadHistory();
|
||
if (tabName === 'weekly') { WEEK_OFFSET = 0; calculateWeeklyScore(); }
|
||
}
|
||
|
||
// ========== 早间立志:动态条目 ==========
|
||
var morningCount = 1;
|
||
function renderMorningItems(values) {
|
||
var container = document.getElementById('morning-items');
|
||
var html = '';
|
||
values = values || [''];
|
||
morningCount = values.length;
|
||
for (var i = 0; i < values.length; i++) {
|
||
html += '<div class="item-row" id="morning-row-' + i + '">' +
|
||
'<div class="item-num">' + (i + 1) + '</div>' +
|
||
'<textarea id="morning-' + i + '" placeholder="第' + (i + 1) + '件最重要的事..." rows="1">' + (values[i] || '') + '</textarea>' +
|
||
(values.length > 1 ? '<div class="item-action"><button class="btn-del" onclick="removeMorning(' + i + ')">×</button></div>' : '') +
|
||
'</div>';
|
||
}
|
||
container.innerHTML = html;
|
||
updateMorningAddBtn();
|
||
}
|
||
function updateMorningAddBtn() {
|
||
var btn = document.getElementById('add-morning-btn');
|
||
btn.style.display = morningCount >= 3 ? 'none' : 'flex';
|
||
}
|
||
function addMorningItem() {
|
||
if (morningCount >= 3) return;
|
||
var vals = [];
|
||
for (var i = 0; i < morningCount; i++) {
|
||
var el = document.getElementById('morning-' + i);
|
||
vals.push(el ? el.value : '');
|
||
}
|
||
vals.push('');
|
||
renderMorningItems(vals);
|
||
}
|
||
function removeMorning(idx) {
|
||
if (morningCount <= 1) return;
|
||
var vals = [];
|
||
for (var i = 0; i < morningCount; i++) {
|
||
if (i !== idx) {
|
||
var el = document.getElementById('morning-' + i);
|
||
vals.push(el ? el.value : '');
|
||
}
|
||
}
|
||
renderMorningItems(vals);
|
||
}
|
||
function getMorningValues() {
|
||
var vals = [];
|
||
for (var i = 0; i < morningCount; i++) {
|
||
var el = document.getElementById('morning-' + i);
|
||
if (el) vals.push(el.value);
|
||
}
|
||
return vals;
|
||
}
|
||
|
||
// ========== 责善·改过:动态条目 ==========
|
||
var reviewCount = 1;
|
||
function renderReviewItems(mistakes, improvements) {
|
||
var container = document.getElementById('review-items');
|
||
var html = '';
|
||
mistakes = mistakes || [''];
|
||
improvements = improvements || [''];
|
||
reviewCount = mistakes.length;
|
||
for (var i = 0; i < mistakes.length; i++) {
|
||
html += '<div class="item-row" id="review-row-' + i + '">' +
|
||
'<div class="item-num" style="background:#764ba2">' + (i + 1) + '</div>' +
|
||
'<div style="flex:1;display:flex;flex-direction:column;gap:4px">' +
|
||
'<textarea id="mistake-' + i + '" placeholder="犯的错/负能量源..." rows="1">' + (mistakes[i] || '') + '</textarea>' +
|
||
'<textarea id="improve-' + i + '" placeholder="下次1步改进行动..." rows="1">' + (improvements[i] || '') + '</textarea>' +
|
||
'</div>' +
|
||
(mistakes.length > 1 ? '<div class="item-action"><button class="btn-del" onclick="removeReview(' + i + ')">×</button></div>' : '') +
|
||
'</div>';
|
||
}
|
||
container.innerHTML = html;
|
||
updateReviewAddBtn();
|
||
}
|
||
function updateReviewAddBtn() {
|
||
var btn = document.getElementById('add-review-btn');
|
||
btn.style.display = reviewCount >= 5 ? 'none' : 'flex';
|
||
}
|
||
function addReviewItem() {
|
||
if (reviewCount >= 5) return;
|
||
var ms = [], ims = [];
|
||
for (var i = 0; i < reviewCount; i++) {
|
||
var me = document.getElementById('mistake-' + i);
|
||
var ie = document.getElementById('improve-' + i);
|
||
ms.push(me ? me.value : '');
|
||
ims.push(ie ? ie.value : '');
|
||
}
|
||
ms.push(''); ims.push('');
|
||
renderReviewItems(ms, ims);
|
||
}
|
||
function removeReview(idx) {
|
||
if (reviewCount <= 1) return;
|
||
var ms = [], ims = [];
|
||
for (var i = 0; i < reviewCount; i++) {
|
||
if (i !== idx) {
|
||
var me = document.getElementById('mistake-' + i);
|
||
var ie = document.getElementById('improve-' + i);
|
||
ms.push(me ? me.value : '');
|
||
ims.push(ie ? ie.value : '');
|
||
}
|
||
}
|
||
renderReviewItems(ms, ims);
|
||
}
|
||
function getReviewValues() {
|
||
var mistakes = [], improvements = [];
|
||
for (var i = 0; i < reviewCount; i++) {
|
||
var me = document.getElementById('mistake-' + i);
|
||
var ie = document.getElementById('improve-' + i);
|
||
mistakes.push(me ? me.value : '');
|
||
improvements.push(ie ? ie.value : '');
|
||
}
|
||
return { mistakes: mistakes, improvements: improvements };
|
||
}
|
||
|
||
// ========== 勤学打卡:动态增减 ==========
|
||
var studyItems = [];
|
||
function renderStudyItems() {
|
||
var container = document.getElementById('study-items');
|
||
if (studyItems.length === 0) {
|
||
container.innerHTML = '<div style="color:#999;font-size:13px;padding:8px">暂无项目,点击下方按钮添加</div>';
|
||
return;
|
||
}
|
||
var html = '';
|
||
for (var i = 0; i < studyItems.length; i++) {
|
||
html += '<div class="check-item">' +
|
||
'<label><input type="checkbox" id="study-' + i + '" ' + (studyItems[i].done ? 'checked' : '') + '>' + studyItems[i].name + '</label>' +
|
||
'<button class="del-btn" onclick="removeStudy(' + i + ')">×</button>' +
|
||
'</div>';
|
||
}
|
||
container.innerHTML = html;
|
||
}
|
||
function addStudyItem() {
|
||
var name = prompt('输入勤学项目名称(如:读一篇文献):');
|
||
if (!name || !name.trim()) return;
|
||
studyItems.push({ name: name.trim(), done: false });
|
||
renderStudyItems();
|
||
}
|
||
function removeStudy(idx) {
|
||
studyItems.splice(idx, 1);
|
||
renderStudyItems();
|
||
}
|
||
function getStudyValues() {
|
||
var result = [];
|
||
for (var i = 0; i < studyItems.length; i++) {
|
||
var cb = document.getElementById('study-' + i);
|
||
result.push({ name: studyItems[i].name, done: cb ? cb.checked : false });
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// ========== 加载/保存打卡 ==========
|
||
function loadChecklist() {
|
||
var dateEl = document.getElementById('check-date');
|
||
if (!dateEl || !dateEl.value) return;
|
||
var date = dateEl.value;
|
||
var all = getData();
|
||
var day = all[date] || {};
|
||
|
||
// 早间立志
|
||
var mvals = day.morningItems || [''];
|
||
renderMorningItems(mvals);
|
||
|
||
// 责善·改过
|
||
var rvals = day.reviewItems || { mistakes: [''], improvements: [''] };
|
||
renderReviewItems(rvals.mistakes || [''], rvals.improvements || ['']);
|
||
|
||
// 勤学打卡:恢复当天保存的项目列表
|
||
if (day.studyItems && day.studyItems.length > 0) {
|
||
studyItems = day.studyItems;
|
||
} else {
|
||
// 默认三项
|
||
studyItems = [
|
||
{ name: 'AI能力有进步', done: false },
|
||
{ name: '管理能力有进步', done: false },
|
||
{ name: '知识储备有进步', done: false }
|
||
];
|
||
}
|
||
renderStudyItems();
|
||
}
|
||
|
||
function saveChecklist() {
|
||
var dateEl = document.getElementById('check-date');
|
||
if (!dateEl || !dateEl.value) { showToast('请先选择日期', 'error'); return; }
|
||
var date = dateEl.value;
|
||
|
||
var all = getData();
|
||
all[date] = {
|
||
morningItems: getMorningValues(),
|
||
reviewItems: getReviewValues(),
|
||
studyItems: getStudyValues(),
|
||
savedAt: new Date().toISOString()
|
||
};
|
||
|
||
if (saveData(all)) {
|
||
showToast('✅ ' + date + ' 打卡保存成功!', 'success');
|
||
} else {
|
||
showToast('❌ 保存失败', 'error');
|
||
}
|
||
}
|
||
|
||
// ========== 每周评分 ==========
|
||
function getMonday(date) {
|
||
var d = new Date(date);
|
||
var day = d.getDay();
|
||
var diff = d.getDate() - day + (day === 0 ? -6 : 1);
|
||
d.setDate(diff);
|
||
return new Date(d);
|
||
}
|
||
|
||
function formatWeekLabel(monday) {
|
||
var sun = new Date(monday);
|
||
sun.setDate(monday.getDate() + 6);
|
||
var m = monday.getMonth() + 1;
|
||
var d1 = monday.getDate();
|
||
var s = sun.getMonth() + 1;
|
||
var d2 = sun.getDate();
|
||
return m + '/' + d1 + ' - ' + s + '/' + d2;
|
||
}
|
||
|
||
function prevWeek() { WEEK_OFFSET--; calculateWeeklyScore(); }
|
||
function nextWeek() { WEEK_OFFSET++; calculateWeeklyScore(); }
|
||
function goThisWeek() { WEEK_OFFSET = 0; calculateWeeklyScore(); }
|
||
|
||
function calculateWeeklyScore() {
|
||
var today = new Date();
|
||
var baseMonday = getMonday(today);
|
||
baseMonday.setDate(baseMonday.getDate() + WEEK_OFFSET * 7);
|
||
var monday = new Date(baseMonday);
|
||
|
||
var label = formatWeekLabel(monday);
|
||
if (WEEK_OFFSET === 0) label = '本周(' + label + ')';
|
||
else if (WEEK_OFFSET === -1) label = '上周(' + label + ')';
|
||
document.getElementById('week-label').textContent = label;
|
||
|
||
var all = getData();
|
||
var totalDays = 0;
|
||
var totalScore = 0;
|
||
var maxScore = 0;
|
||
var details = [];
|
||
|
||
for (var i = 0; i < 7; i++) {
|
||
var cur = new Date(monday);
|
||
cur.setDate(monday.getDate() + i);
|
||
var ds = cur.toISOString().split('T')[0];
|
||
var dayData = all[ds];
|
||
|
||
if (dayData) {
|
||
totalDays++;
|
||
var dayMax = 0, dayGot = 0;
|
||
|
||
// 立志得分:填写了的重要事项数 / 总条目数
|
||
if (dayData.morningItems && dayData.morningItems.length > 0) {
|
||
dayMax += dayData.morningItems.length;
|
||
for (var j = 0; j < dayData.morningItems.length; j++) {
|
||
if (dayData.morningItems[j] && dayData.morningItems[j].trim()) dayGot++;
|
||
}
|
||
}
|
||
|
||
// 改过得分:每条反思都有文字
|
||
if (dayData.reviewItems && dayData.reviewItems.mistakes) {
|
||
dayMax += dayData.reviewItems.mistakes.length * 2; // 错 + 改进
|
||
for (var k = 0; k < dayData.reviewItems.mistakes.length; k++) {
|
||
if (dayData.reviewItems.mistakes[k] && dayData.reviewItems.mistakes[k].trim()) dayGot++;
|
||
if (dayData.reviewItems.improvements && dayData.reviewItems.improvements[k] && dayData.reviewItems.improvements[k].trim()) dayGot++;
|
||
}
|
||
}
|
||
|
||
// 勤学得分
|
||
if (dayData.studyItems && dayData.studyItems.length > 0) {
|
||
dayMax += dayData.studyItems.length;
|
||
for (var m = 0; m < dayData.studyItems.length; m++) {
|
||
if (dayData.studyItems[m].done) dayGot++;
|
||
}
|
||
}
|
||
|
||
totalScore += dayGot;
|
||
maxScore += dayMax;
|
||
|
||
var dayPct = dayMax > 0 ? Math.round((dayGot / dayMax) * 100) : 0;
|
||
var icon = dayPct >= 70 ? '✅' : dayPct >= 40 ? '⚠️' : '❌';
|
||
details.push('<div class="day-row">' +
|
||
'<span style="color:#667eea;min-width:90px">' + ds + '</span>' +
|
||
'<span style="flex:1">' + dayGot + '/' + dayMax + '</span>' +
|
||
'<span>' + icon + ' ' + dayPct + '%</span></div>');
|
||
}
|
||
}
|
||
|
||
var score = maxScore > 0 ? Math.round((totalScore / maxScore) * 100) : 0;
|
||
document.getElementById('weekly-score').textContent = score;
|
||
document.getElementById('score-bar').style.width = score + '%';
|
||
|
||
var txt = '';
|
||
if (score >= 90) txt = '🌟 卓越!磁场非常强大';
|
||
else if (score >= 70) txt = '💪 良好,继续保持';
|
||
else if (score >= 50) txt = '⚠️ 一般,需要加强';
|
||
else txt = '❌ 较弱,急需调整';
|
||
|
||
document.getElementById('score-text').textContent = txt;
|
||
document.getElementById('weekly-details').innerHTML = details.length > 0
|
||
? '<div style="font-size:12px;color:#999;margin-bottom:8px">每日得分详情:</div>' + details.join('')
|
||
: '<div style="text-align:center;color:#999;padding:16px">本周暂无打卡记录</div>';
|
||
}
|
||
|
||
// ========== 历史 ==========
|
||
function loadHistory() {
|
||
var all = getData();
|
||
var dates = Object.keys(all).sort().reverse();
|
||
var el = document.getElementById('history-list');
|
||
|
||
if (dates.length === 0) {
|
||
el.innerHTML = '<div class="empty-state">暂无打卡记录</div>';
|
||
return;
|
||
}
|
||
|
||
var html = '';
|
||
for (var i = 0; i < dates.length; i++) {
|
||
var date = dates[i];
|
||
var dd = all[date];
|
||
var morningCount = dd.morningItems ? dd.morningItems.filter(function(v){return v && v.trim()}).length : 0;
|
||
var reviewCount = dd.reviewItems && dd.reviewItems.mistakes ? dd.reviewItems.mistakes.filter(function(v){return v && v.trim()}).length : 0;
|
||
var studyDone = dd.studyItems ? dd.studyItems.filter(function(v){return v.done}).length : 0;
|
||
var studyTotal = dd.studyItems ? dd.studyItems.length : 0;
|
||
html += '<div class="history-item">' +
|
||
'<div class="date">' + date + '</div>' +
|
||
'<div class="note">' +
|
||
(morningCount > 0 ? '<span class="tag done">立志 ' + morningCount + '条</span>' : '<span class="tag miss">未立志</span>') +
|
||
(reviewCount > 0 ? '<span class="tag done">改过 ' + reviewCount + '条</span>' : '<span class="tag miss">未改过</span>') +
|
||
'<span class="tag ' + (studyDone > 0 ? 'done' : 'miss') + '">勤学 ' + studyDone + '/' + studyTotal + '</span>' +
|
||
'</div></div>';
|
||
}
|
||
el.innerHTML = html;
|
||
}
|
||
|
||
// ========== 初始化 ==========
|
||
(function init() {
|
||
var today = new Date().toISOString().split('T')[0];
|
||
var cd = document.getElementById('check-date');
|
||
if (cd) cd.value = today;
|
||
// 初始化默认 study items
|
||
studyItems = [
|
||
{ name: 'AI能力有进步', done: false },
|
||
{ name: '管理能力有进步', done: false },
|
||
{ name: '知识储备有进步', done: false }
|
||
];
|
||
loadChecklist();
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|