Lashtw commited on
Commit
737c7fe
·
verified ·
1 Parent(s): 0e20069

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +59 -43
index.html CHANGED
@@ -203,10 +203,27 @@
203
  touch-action: none;
204
  }
205
 
206
- .board-card[data-cat="exam"] { --theme-color: #38bdf8; }
207
- .board-card[data-cat="sports"] { --theme-color: #f97316; }
208
- .board-card[data-cat="event"] { --theme-color: #ec4899; }
209
- .board-card[data-cat="life"] { --theme-color: #10b981; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  .board-card::before {
212
  content: '';
@@ -219,9 +236,13 @@
219
  z-index: 2;
220
  }
221
 
 
222
  .board-card.highlight {
223
  border: 1.8px solid #fbbf24;
224
- box-shadow: 0 16px 40px rgba(251, 191, 36, 0.25);
 
 
 
225
  }
226
  .board-card.highlight::before {
227
  background: #fbbf24;
@@ -262,7 +283,6 @@
262
  }
263
  .cat-icon svg { width: 20px; height: 20px; }
264
  .board-card.highlight .cat-icon {
265
- color: #fbbf24;
266
  background: rgba(251, 191, 36, 0.16);
267
  }
268
  .card-title {
@@ -280,6 +300,7 @@
280
  padding-left: 2px;
281
  }
282
 
 
283
  .card-center-metric {
284
  flex: 1;
285
  display: flex;
@@ -294,15 +315,13 @@
294
  line-height: 1;
295
  letter-spacing: -2px;
296
  font-feature-settings: "tnum";
297
- color: var(--primary-text);
298
- }
299
- .board-card.highlight .metric-number {
300
- color: #fbbf24;
301
- text-shadow: 0 0 30px rgba(251, 191, 36, 0.4);
302
  }
303
  .metric-unit {
304
  font-size: 1.2rem;
305
- color: var(--secondary-text);
 
306
  font-weight: 500;
307
  }
308
 
@@ -324,9 +343,6 @@
324
  border-radius: 999px;
325
  transition: width 0.4s ease;
326
  }
327
- .board-card.highlight .progress-fill {
328
- background: #fbbf24;
329
- }
330
  .metric-details {
331
  display: flex;
332
  justify-content: space-between;
@@ -601,7 +617,7 @@
601
 
602
  <!-- 編輯狀態控制列 -->
603
  <div class="edit-banner" id="editBanner">
604
- <span style="font-size:0.85rem; color:#38bdf8;">✦ 自由排版中:拖曳卡片或拉動右下角角標</span>
605
  <button class="btn btn-secondary" onclick="randomizeQuote()">隨機金句</button>
606
  <button class="btn btn-secondary" onclick="openAdminDrawer()">作息與設定</button>
607
  <button class="btn btn-success" onclick="exitEditMode()">完成並鎖定</button>
@@ -653,10 +669,9 @@
653
  </div>
654
 
655
  <div class="drawer-content">
656
- <!-- 固化預設值與資料備份核心 -->
657
  <div class="setting-block" style="border: 1px solid #38bdf8;">
658
  <h4>永久固化排版 (解決重開機重設問題)</h4>
659
- <p style="font-size:0.8rem; color:#94a3b8;">排版好後,點擊下方「固化為全新預設檔」,將下載的檔案直接取代原本的 `index.html`,重開機保證 100% 永不跑位。</p>
660
 
661
  <div style="display:flex; flex-direction:column; gap:8px;">
662
  <button class="btn btn-success" style="padding:10px; font-size:0.9rem;" onclick="exportAsHardcodedHtml()">⭐ 固化為全新預設檔 (下載 index.html)</button>
@@ -691,7 +706,7 @@
691
 
692
  <div class="setting-block">
693
  <div style="display:flex; justify-content:space-between; align-items:center;">
694
- <h4>倒數項目資料庫</h4>
695
  <button class="btn btn-primary" onclick="addNewEvent()">+ 新增卡片</button>
696
  </div>
697
  <div id="editorItemList" style="display:flex; flex-direction:column; gap:10px;"></div>
@@ -825,7 +840,6 @@
825
  "16:00-16:45"
826
  ];
827
 
828
- // 本地預設種子(可透過一鍵固化功能直接改寫)
829
  /*START_DEFAULT_DATA*/
830
  const DEFAULT_DATA = {
831
  theme: "dark-slate",
@@ -845,9 +859,6 @@
845
  let isClassBreak = false;
846
  let currentPin = "";
847
 
848
- // =========================================
849
- // IndexedDB 持久化雙重快取架構
850
- // =========================================
851
  function openDB() {
852
  return new Promise((resolve) => {
853
  const req = indexedDB.open("ClassroomFocusDB", 1);
@@ -901,14 +912,10 @@
901
  saveToIndexedDB(appState);
902
  }
903
 
904
- // =========================================
905
- // 固化為全新預設檔 (下載即可徹底解決跑位)
906
- // =========================================
907
  function exportAsHardcodedHtml() {
908
  let currentHtml = document.documentElement.outerHTML;
909
  const targetDataString = JSON.stringify(appState, null, 2);
910
 
911
- // 正則精準替換 DEFAULT_DATA 變數區塊
912
  const regex = /\/\*START_DEFAULT_DATA\*\/[\s\S]*?\/\*END_DEFAULT_DATA\*\//;
913
  const replacement = `/*START_DEFAULT_DATA*/\n const DEFAULT_DATA = ${targetDataString};\n /*END_DEFAULT_DATA*/`;
914
 
@@ -924,7 +931,7 @@
924
  document.body.removeChild(a);
925
  URL.revokeObjectURL(url);
926
 
927
- alert("✓ 固化成功!已為您下載最新的 `index.html`。\n請用這個檔案直接覆蓋 Lively 中的原檔,以後開機將原生讀取這份排版,永不重設!");
928
  }
929
 
930
  function openPinModal() {
@@ -1021,7 +1028,7 @@
1021
  renderBoard();
1022
  updateClock();
1023
  closeAdminDrawer();
1024
- alert("✓ 設定已成功匯入並寫入持久快取!");
1025
  } else {
1026
  alert("設定檔格式不符。");
1027
  }
@@ -1202,6 +1209,7 @@
1202
  });
1203
  }
1204
 
 
1205
  const canvas = document.getElementById("aurora-canvas");
1206
  const ctx = canvas.getContext("2d");
1207
  let animId = null;
@@ -1218,9 +1226,11 @@
1218
  ctx.clearRect(0, 0, canvas.width, canvas.height);
1219
  step += 0.008;
1220
 
1221
- const highlightCard = appState.cards.find(c => c.highlight);
1222
- const focalX = highlightCard ? (highlightCard.x + highlightCard.w / 2) : canvas.width * 0.7;
1223
- const focalY = highlightCard ? (highlightCard.y + highlightCard.h / 2) : canvas.height * 0.4;
 
 
1224
 
1225
  const colors = [
1226
  { r: 16, g: 185, b: 129, a: 0.18 },
@@ -1261,17 +1271,20 @@
1261
  ctx.filter = "none";
1262
  });
1263
 
1264
- if (highlightCard) {
1265
- const radGrad = ctx.createRadialGradient(focalX, focalY, 30, focalX, focalY, highlightCard.w * 0.85);
1266
- radGrad.addColorStop(0, "rgba(251, 191, 36, 0.18)");
 
 
 
1267
  radGrad.addColorStop(0.6, "rgba(56, 189, 248, 0.10)");
1268
  radGrad.addColorStop(1, "rgba(0, 0, 0, 0)");
1269
 
1270
  ctx.beginPath();
1271
- ctx.arc(focalX, focalY, highlightCard.w * 0.85, 0, Math.PI * 2);
1272
  ctx.fillStyle = radGrad;
1273
  ctx.fill();
1274
- }
1275
 
1276
  if (isClassBreak) {
1277
  animId = requestAnimationFrame(renderAuroraWaves);
@@ -1362,14 +1375,14 @@
1362
  <input type="date" value="${item.date}" onchange="appState.cards[${index}].date=this.value">
1363
  </div>
1364
  <div style="display:flex; justify-content:space-between; align-items:center;">
1365
- <select onchange="appState.cards[${index}].cat=this.value">
1366
  <option value="exam" ${item.cat==='exam'?'selected':''}>學業考試 (書本)</option>
1367
  <option value="sports" ${item.cat==='sports'?'selected':''}>運動競賽 (獎盃)</option>
1368
  <option value="event" ${item.cat==='event'?'selected':''}>校慶活動 (旗幟)</option>
1369
  <option value="life" ${item.cat==='life'?'selected':''}>常態生活 (時鐘)</option>
1370
  </select>
1371
- <label style="font-size:0.8rem; color:#cbd5e1; display:flex; align-items:center; gap:4px;">
1372
- <input type="checkbox" ${item.highlight ? 'checked':''} onchange="setHighlightCard(${index}, this.checked)"> 重要高亮
1373
  </label>
1374
  <button class="btn btn-danger" style="padding:4px 8px;" onclick="removeCard(${index})">刪除</button>
1375
  </div>
@@ -1378,9 +1391,10 @@
1378
  });
1379
  }
1380
 
1381
- function setHighlightCard(idx, isChecked) {
1382
- appState.cards.forEach((c, i) => c.highlight = (i === idx && isChecked));
1383
- renderDrawerEditor();
 
1384
  }
1385
 
1386
  function addNewEvent() {
@@ -1398,11 +1412,13 @@
1398
  totalSpan: 100
1399
  });
1400
  renderDrawerEditor();
 
1401
  }
1402
 
1403
  function removeCard(idx) {
1404
  appState.cards.splice(idx, 1);
1405
  renderDrawerEditor();
 
1406
  }
1407
 
1408
  function saveAllSettings() {
 
203
  touch-action: none;
204
  }
205
 
206
+ /* 4 大分類的主題代表色 */
207
+ .board-card[data-cat="exam"] {
208
+ --theme-color: #38bdf8;
209
+ --num-color: #38bdf8;
210
+ --num-glow: rgba(56, 189, 248, 0.35);
211
+ }
212
+ .board-card[data-cat="sports"] {
213
+ --theme-color: #f97316;
214
+ --num-color: #fb923c;
215
+ --num-glow: rgba(249, 115, 22, 0.35);
216
+ }
217
+ .board-card[data-cat="event"] {
218
+ --theme-color: #ec4899;
219
+ --num-color: #f472b6;
220
+ --num-glow: rgba(236, 72, 153, 0.35);
221
+ }
222
+ .board-card[data-cat="life"] {
223
+ --theme-color: #10b981;
224
+ --num-color: #34d399;
225
+ --num-glow: rgba(16, 185, 129, 0.35);
226
+ }
227
 
228
  .board-card::before {
229
  content: '';
 
236
  z-index: 2;
237
  }
238
 
239
+ /* 重點高亮卡片:覆蓋為極致琥珀金強調色 */
240
  .board-card.highlight {
241
  border: 1.8px solid #fbbf24;
242
+ box-shadow: 0 16px 40px rgba(251, 191, 36, 0.28);
243
+ --theme-color: #fbbf24;
244
+ --num-color: #fbbf24;
245
+ --num-glow: rgba(251, 191, 36, 0.45);
246
  }
247
  .board-card.highlight::before {
248
  background: #fbbf24;
 
283
  }
284
  .cat-icon svg { width: 20px; height: 20px; }
285
  .board-card.highlight .cat-icon {
 
286
  background: rgba(251, 191, 36, 0.16);
287
  }
288
  .card-title {
 
300
  padding-left: 2px;
301
  }
302
 
303
+ /* 數字文字色彩重新連動主題色 */
304
  .card-center-metric {
305
  flex: 1;
306
  display: flex;
 
315
  line-height: 1;
316
  letter-spacing: -2px;
317
  font-feature-settings: "tnum";
318
+ color: var(--num-color);
319
+ text-shadow: 0 0 24px var(--num-glow);
 
 
 
320
  }
321
  .metric-unit {
322
  font-size: 1.2rem;
323
+ color: var(--theme-color);
324
+ opacity: 0.85;
325
  font-weight: 500;
326
  }
327
 
 
343
  border-radius: 999px;
344
  transition: width 0.4s ease;
345
  }
 
 
 
346
  .metric-details {
347
  display: flex;
348
  justify-content: space-between;
 
617
 
618
  <!-- 編輯狀態控制列 -->
619
  <div class="edit-banner" id="editBanner">
620
+ <span style="font-size:0.85rem; color:#38bdf8;">✦ 自由排版中:拖曳卡片或縮放邊角</span>
621
  <button class="btn btn-secondary" onclick="randomizeQuote()">隨機金句</button>
622
  <button class="btn btn-secondary" onclick="openAdminDrawer()">作息與設定</button>
623
  <button class="btn btn-success" onclick="exitEditMode()">完成並鎖定</button>
 
669
  </div>
670
 
671
  <div class="drawer-content">
 
672
  <div class="setting-block" style="border: 1px solid #38bdf8;">
673
  <h4>永久固化排版 (解決重開機重設問題)</h4>
674
+ <p style="font-size:0.8rem; color:#94a3b8;">排版完成後,點擊下方「固化為全新預設檔」,下載覆蓋原本的 `index.html`,重開機保證 100% 永不跑位。</p>
675
 
676
  <div style="display:flex; flex-direction:column; gap:8px;">
677
  <button class="btn btn-success" style="padding:10px; font-size:0.9rem;" onclick="exportAsHardcodedHtml()">⭐ 固化為全新預設檔 (下載 index.html)</button>
 
706
 
707
  <div class="setting-block">
708
  <div style="display:flex; justify-content:space-between; align-items:center;">
709
+ <h4>倒數項目資料庫 (可複選多個高亮)</h4>
710
  <button class="btn btn-primary" onclick="addNewEvent()">+ 新增卡片</button>
711
  </div>
712
  <div id="editorItemList" style="display:flex; flex-direction:column; gap:10px;"></div>
 
840
  "16:00-16:45"
841
  ];
842
 
 
843
  /*START_DEFAULT_DATA*/
844
  const DEFAULT_DATA = {
845
  theme: "dark-slate",
 
859
  let isClassBreak = false;
860
  let currentPin = "";
861
 
 
 
 
862
  function openDB() {
863
  return new Promise((resolve) => {
864
  const req = indexedDB.open("ClassroomFocusDB", 1);
 
912
  saveToIndexedDB(appState);
913
  }
914
 
 
 
 
915
  function exportAsHardcodedHtml() {
916
  let currentHtml = document.documentElement.outerHTML;
917
  const targetDataString = JSON.stringify(appState, null, 2);
918
 
 
919
  const regex = /\/\*START_DEFAULT_DATA\*\/[\s\S]*?\/\*END_DEFAULT_DATA\*\//;
920
  const replacement = `/*START_DEFAULT_DATA*/\n const DEFAULT_DATA = ${targetDataString};\n /*END_DEFAULT_DATA*/`;
921
 
 
931
  document.body.removeChild(a);
932
  URL.revokeObjectURL(url);
933
 
934
+ alert("✓ 固化成功!請用剛下載的 `index.html` 直接覆蓋 Lively 資料夾內的原檔,開機將永久預設此版面。");
935
  }
936
 
937
  function openPinModal() {
 
1028
  renderBoard();
1029
  updateClock();
1030
  closeAdminDrawer();
1031
+ alert("✓ 設定已成功匯入!所有排版、顏色與重點標記已即刻生效。");
1032
  } else {
1033
  alert("設定檔格式不符。");
1034
  }
 
1209
  });
1210
  }
1211
 
1212
+ // 極光引擎 (支援多重高亮焦點光暈)
1213
  const canvas = document.getElementById("aurora-canvas");
1214
  const ctx = canvas.getContext("2d");
1215
  let animId = null;
 
1226
  ctx.clearRect(0, 0, canvas.width, canvas.height);
1227
  step += 0.008;
1228
 
1229
+ // 抓取所有被設為高亮的卡片
1230
+ const highlightCards = appState.cards.filter(c => c.highlight);
1231
+ const primaryHighlight = highlightCards[0];
1232
+ const focalX = primaryHighlight ? (primaryHighlight.x + primaryHighlight.w / 2) : canvas.width * 0.7;
1233
+ const focalY = primaryHighlight ? (primaryHighlight.y + primaryHighlight.h / 2) : canvas.height * 0.4;
1234
 
1235
  const colors = [
1236
  { r: 16, g: 185, b: 129, a: 0.18 },
 
1271
  ctx.filter = "none";
1272
  });
1273
 
1274
+ // 為所有複選高亮的卡片同時繪製共振金色光暈
1275
+ highlightCards.forEach(c => {
1276
+ const cx = c.x + c.w / 2;
1277
+ const cy = c.y + c.h / 2;
1278
+ const radGrad = ctx.createRadialGradient(cx, cy, 30, cx, cy, c.w * 0.85);
1279
+ radGrad.addColorStop(0, "rgba(251, 191, 36, 0.20)");
1280
  radGrad.addColorStop(0.6, "rgba(56, 189, 248, 0.10)");
1281
  radGrad.addColorStop(1, "rgba(0, 0, 0, 0)");
1282
 
1283
  ctx.beginPath();
1284
+ ctx.arc(cx, cy, c.w * 0.85, 0, Math.PI * 2);
1285
  ctx.fillStyle = radGrad;
1286
  ctx.fill();
1287
+ });
1288
 
1289
  if (isClassBreak) {
1290
  animId = requestAnimationFrame(renderAuroraWaves);
 
1375
  <input type="date" value="${item.date}" onchange="appState.cards[${index}].date=this.value">
1376
  </div>
1377
  <div style="display:flex; justify-content:space-between; align-items:center;">
1378
+ <select onchange="appState.cards[${index}].cat=this.value; renderBoard();">
1379
  <option value="exam" ${item.cat==='exam'?'selected':''}>學業考試 (書本)</option>
1380
  <option value="sports" ${item.cat==='sports'?'selected':''}>運動競賽 (獎盃)</option>
1381
  <option value="event" ${item.cat==='event'?'selected':''}>校慶活動 (旗幟)</option>
1382
  <option value="life" ${item.cat==='life'?'selected':''}>常態生活 (時鐘)</option>
1383
  </select>
1384
+ <label style="font-size:0.8rem; color:#cbd5e1; display:flex; align-items:center; gap:4px; cursor:pointer;">
1385
+ <input type="checkbox" ${item.highlight ? 'checked':''} onchange="toggleCardHighlight(${index}, this.checked)"> 重要高亮
1386
  </label>
1387
  <button class="btn btn-danger" style="padding:4px 8px;" onclick="removeCard(${index})">刪除</button>
1388
  </div>
 
1391
  });
1392
  }
1393
 
1394
+ // 支援複選高亮
1395
+ function toggleCardHighlight(idx, isChecked) {
1396
+ appState.cards[idx].highlight = isChecked;
1397
+ renderBoard();
1398
  }
1399
 
1400
  function addNewEvent() {
 
1412
  totalSpan: 100
1413
  });
1414
  renderDrawerEditor();
1415
+ renderBoard();
1416
  }
1417
 
1418
  function removeCard(idx) {
1419
  appState.cards.splice(idx, 1);
1420
  renderDrawerEditor();
1421
+ renderBoard();
1422
  }
1423
 
1424
  function saveAllSettings() {