Lashtw commited on
Commit
d86a13d
·
verified ·
1 Parent(s): 4919e24

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +157 -11
index.html CHANGED
@@ -118,8 +118,8 @@
118
 
119
  <!-- Grid Settings -->
120
  <div>
121
- <label class="block text-sm font-bold text-slate-700 mb-2">📐 網格設定 (點擊切換)</label>
122
- <div class="grid grid-cols-3 gap-2">
123
  <button
124
  v-for="conf in gridOptions"
125
  :key="conf.label"
@@ -130,6 +130,16 @@
130
  {{ conf.label }}
131
  </button>
132
  </div>
 
 
 
 
 
 
 
 
 
 
133
  </div>
134
 
135
  <!-- Template -->
@@ -139,11 +149,47 @@
139
  @click="applyTemplate('lucky')"
140
  class="w-full py-3 bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 text-white font-bold rounded-lg shadow-md hover:shadow-lg active:scale-95 transition-all flex items-center justify-center gap-2"
141
  >
142
- <svg viewBox="0 0 24 24" class="w-5 h-5 fill-current"><path d="M12,2C9,2,6,4,6,7c0-2,3-5,3-5S6,0,9,0c4,0,5,5,2,8c3-3,8-2,8,2s-5,5-8,2c2,2,2,7,0,7c0-3-3-5-3-5s-1,4-4,4c0-4,5-5,2-8C6,13,1,12,1,8C1,8,6,7,9,10C10,11,11,11,12,10C13,9,12,2,12,2z"></path></svg>
 
 
 
143
  套用:幸運遇見你 (如皓老師版)
144
  </button>
145
  <p class="text-xs text-slate-400 mt-2">提示:套用後會自動切換為 6x8 網格並填入內容。</p>
146
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  <!-- Instruction -->
149
  <div class="bg-indigo-50 p-4 rounded-lg border border-indigo-100 text-sm text-indigo-800">
@@ -363,15 +409,17 @@
363
 
364
  // --- Icons (Updated Clover) ---
365
  const icons = {
366
- // 修正後的幸運草:四個愛心尖端朝內 (12,12)
 
367
  '幸運草': `
368
- M12,12 C9,8 5,5 5,3 C5,1 7,0 9,0 C10.5,0 11.5,1 12,2 C12.5,1 13.5,0 15,0 C17,0 19,1 19,3 C19,5 15,8 12,12 z
369
- M12,12 C16,9 19,5 21,5 C23,5 24,7 24,9 C24,10.5 23,11.5 22,12 C23,12.5 24,13.5 24,15 C24,17 23,19 21,19 C19,19 16,15 12,12 z
370
- M12,12 C15,16 19,19 19,21 C19,23 17,24 15,24 C13.5,24 12.5,23 12,22 C11.5,23 10.5,24 9,24 C7,24 5,23 5,21 C5,19 9,16 12,12 z
371
- M12,12 C8,15 5,19 3,19 C1,19 0,17 0,15 C0,13.5 1,12.5 2,12 C1,11.5 0,10.5 0,9 C0,7 1,5 3,5 C5,5 8,9 12,12 z
 
372
  `,
373
  '愛心': 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
374
- '星星': 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z',
375
  '勝利': 'M16.5 13c-.55 0-1 .45-1 1v5h-1v-5c0-.55-.45-1-1-1s-1 .45-1 1v5h-1v-5c0-.55-.45-1-1-1s-1 .45-1 1v2.5c0 .55-.45 1-1 1s-1-.45-1-1V5.63c0-1-.7-1.63-1.6-1.63-.88 0-1.6.82-1.6 1.73V13h-1V5.73C5.3 3.66 7.03 2 9.1 2c1.77 0 3.32 1.22 3.8 2.87.66-1.07 1.8-1.87 3.1-1.87 2.21 0 4 1.79 4 4v6c0 .55-.45 1-1 1s-1-.45-1-1v-1h-1.5v1z M21 16c0 2.97-2.16 5.43-5 5.91V22h-8v-2.09c-2.84-.48-5-2.94-5-5.91h2c0 2.76 2.24 5 5 5s5-2.24 5-5h2z',
376
  '獎盃': 'M20.2 6.5C19.7 3.9 17.5 2 15 2H9C6.5 2 4.3 3.9 3.8 6.5L3 11c-.5 2.5 1.2 5 3.8 5.8V17c0 2.2 1.8 4 4 4h2.4c2.2 0 4-1.8 4-4v-.2c2.6-.8 4.3-3.3 3.8-5.8l-.8-4.5zM6.5 10.6l.6-3.8C7.4 4.8 9.1 4 9 4h6c-.1 0 1.6.8 1.9 2.8l.6 3.8c.2 1.3-.8 2.4-2.1 2.4h-9c-1.3 0-2.3-1.1-2.1-2.4z M17 17c0 1.1-.9 2-2 2H9c-1.1 0-2-.9-2-2v-1h10v1z M15 22H9v1h6v-1z',
377
  '笑臉': 'M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z',
@@ -408,13 +456,25 @@
408
  const inputBuffer = ref('');
409
  const isGenerating = ref(false);
410
  const textInputRef = ref(null);
 
411
 
412
  const activePageCells = computed(() => pages.value[activePageId.value - 1].cells);
413
 
414
  // --- Actions ---
415
 
416
  const changeGridSize = (conf) => {
417
- // 移除了 confirm() 對話框,直接執行切換
 
 
 
 
 
 
 
 
 
 
 
418
  currentGrid.value = conf;
419
  const totalCells = conf.rows * conf.cols;
420
 
@@ -430,6 +490,31 @@
430
  viewMode.value = 'overview';
431
  };
432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
  // Helper to set cell content easily using 1-based Row/Col
434
  // Row: 1-8, Col: 1-6
435
  const setCell = (pageIndex, row, col, type, content, rotation = 0) => {
@@ -446,6 +531,62 @@
446
  }
447
  };
448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  const applyTemplate = (templateId) => {
450
  // 移除了 confirm() 對話框,直接套用模板
451
  try {
@@ -686,7 +827,12 @@
686
  updateSelectedCellText,
687
  applyIconToCell,
688
  clearCurrentCell,
689
- exportPDF
 
 
 
 
 
690
  };
691
  }
692
  }).mount('#app');
 
118
 
119
  <!-- Grid Settings -->
120
  <div>
121
+ <label class="block text-sm font-bold text-slate-700 mb-2">📐 網格設定</label>
122
+ <div class="grid grid-cols-3 gap-2 mb-2">
123
  <button
124
  v-for="conf in gridOptions"
125
  :key="conf.label"
 
130
  {{ conf.label }}
131
  </button>
132
  </div>
133
+ <!-- New Clear All Button -->
134
+ <button
135
+ @click="clearAllContent"
136
+ class="w-full py-2 text-sm text-red-600 border border-red-200 bg-red-50 hover:bg-red-100 rounded-lg transition-all flex items-center justify-center gap-1"
137
+ >
138
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
139
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
140
+ </svg>
141
+ 一鍵清空所有內容
142
+ </button>
143
  </div>
144
 
145
  <!-- Template -->
 
149
  @click="applyTemplate('lucky')"
150
  class="w-full py-3 bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 text-white font-bold rounded-lg shadow-md hover:shadow-lg active:scale-95 transition-all flex items-center justify-center gap-2"
151
  >
152
+ <!-- 更新這裡的 SVG 為新的帶梗幸運草 -->
153
+ <svg viewBox="0 0 24 24" class="w-5 h-5 fill-current">
154
+ <path d="M12,12 m-2,-2 a3,3 0 0,1 6,0 a3,3 0 0,1 -6,0 M12,12 m2,-2 a3,3 0 0,1 0,6 a3,3 0 0,1 0,-6 M12,12 m2,2 a3,3 0 0,1 -6,0 a3,3 0 0,1 6,0 M12,12 m-2,2 a3,3 0 0,1 0,-6 a3,3 0 0,1 0,6 M14,14 Q18,18 20,24 L22,23 Q19,16 14,14 Z"></path>
155
+ </svg>
156
  套用:幸運遇見你 (如皓老師版)
157
  </button>
158
  <p class="text-xs text-slate-400 mt-2">提示:套用後會自動切換為 6x8 網格並填入內容。</p>
159
  </div>
160
+
161
+ <!-- Project Management (New Feature) -->
162
+ <div class="border-t border-slate-200 pt-4">
163
+ <label class="block text-sm font-bold text-slate-700 mb-2">💾 專案管理</label>
164
+ <div class="grid grid-cols-2 gap-2">
165
+ <button
166
+ @click="exportProject"
167
+ class="py-2 bg-slate-600 hover:bg-slate-700 text-white font-bold rounded-lg shadow-sm active:scale-95 transition-all flex items-center justify-center gap-1 text-sm"
168
+ >
169
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
170
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
171
+ </svg>
172
+ 匯出存檔
173
+ </button>
174
+ <button
175
+ @click="triggerImport"
176
+ class="py-2 bg-slate-600 hover:bg-slate-700 text-white font-bold rounded-lg shadow-sm active:scale-95 transition-all flex items-center justify-center gap-1 text-sm"
177
+ >
178
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
179
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m-4 4v12" />
180
+ </svg>
181
+ 匯入舊檔
182
+ </button>
183
+ <input
184
+ type="file"
185
+ ref="fileInputRef"
186
+ class="hidden"
187
+ accept=".json"
188
+ @change="importProject"
189
+ >
190
+ </div>
191
+ <p class="text-xs text-slate-400 mt-2">下載 .json 檔可保留目前進度,下次上課可���入繼續編輯。</p>
192
+ </div>
193
 
194
  <!-- Instruction -->
195
  <div class="bg-indigo-50 p-4 rounded-lg border border-indigo-100 text-sm text-indigo-800">
 
409
 
410
  // --- Icons (Updated Clover) ---
411
  const icons = {
412
+ // 再次修正幸運草:縮小葉片範圍,確保右下角的梗(stem)不會被覆蓋
413
+ // 使用四個圓形/心形組成中心,加上明顯的右下角彎曲梗
414
  '幸運草': `
415
+ M9,12 a3,3 0 1,1 6,0 a3,3 0 1,1 -6,0
416
+ M12,9 a3,3 0 1,1 0,6 a3,3 0 1,1 0,-6
417
+ M9,9 a3,3 0 1,1 6,0 a3,3 0 1,1 -6,0
418
+ M12,12 a3,3 0 1,1 -6,0 a3,3 0 1,1 6,0
419
+ M13.5,13.5 Q17,17 19,23 L21,22 Q18,15 13.5,13.5 Z
420
  `,
421
  '愛心': 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
422
+ '星星': 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z',
423
  '勝利': 'M16.5 13c-.55 0-1 .45-1 1v5h-1v-5c0-.55-.45-1-1-1s-1 .45-1 1v5h-1v-5c0-.55-.45-1-1-1s-1 .45-1 1v2.5c0 .55-.45 1-1 1s-1-.45-1-1V5.63c0-1-.7-1.63-1.6-1.63-.88 0-1.6.82-1.6 1.73V13h-1V5.73C5.3 3.66 7.03 2 9.1 2c1.77 0 3.32 1.22 3.8 2.87.66-1.07 1.8-1.87 3.1-1.87 2.21 0 4 1.79 4 4v6c0 .55-.45 1-1 1s-1-.45-1-1v-1h-1.5v1z M21 16c0 2.97-2.16 5.43-5 5.91V22h-8v-2.09c-2.84-.48-5-2.94-5-5.91h2c0 2.76 2.24 5 5 5s5-2.24 5-5h2z',
424
  '獎盃': 'M20.2 6.5C19.7 3.9 17.5 2 15 2H9C6.5 2 4.3 3.9 3.8 6.5L3 11c-.5 2.5 1.2 5 3.8 5.8V17c0 2.2 1.8 4 4 4h2.4c2.2 0 4-1.8 4-4v-.2c2.6-.8 4.3-3.3 3.8-5.8l-.8-4.5zM6.5 10.6l.6-3.8C7.4 4.8 9.1 4 9 4h6c-.1 0 1.6.8 1.9 2.8l.6 3.8c.2 1.3-.8 2.4-2.1 2.4h-9c-1.3 0-2.3-1.1-2.1-2.4z M17 17c0 1.1-.9 2-2 2H9c-1.1 0-2-.9-2-2v-1h10v1z M15 22H9v1h6v-1z',
425
  '笑臉': 'M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z',
 
456
  const inputBuffer = ref('');
457
  const isGenerating = ref(false);
458
  const textInputRef = ref(null);
459
+ const fileInputRef = ref(null); // Reference for file input
460
 
461
  const activePageCells = computed(() => pages.value[activePageId.value - 1].cells);
462
 
463
  // --- Actions ---
464
 
465
  const changeGridSize = (conf) => {
466
+ // 如果是重複點擊目前的網格,不做任何事
467
+ if (currentGrid.value.label === conf.label) return;
468
+
469
+ // 檢查是否有內容 (防止誤觸清空)
470
+ const hasContent = pages.value.some(p => p.cells.some(c => c.content !== ''));
471
+
472
+ if (hasContent) {
473
+ alert("若要切換網格設定請清除內容後再切換。");
474
+ return;
475
+ }
476
+
477
+ // 執行切換 (無內容時直接切換)
478
  currentGrid.value = conf;
479
  const totalCells = conf.rows * conf.cols;
480
 
 
490
  viewMode.value = 'overview';
491
  };
492
 
493
+ const clearAllContent = () => {
494
+ const hasContent = pages.value.some(p => p.cells.some(c => c.content !== ''));
495
+ if (!hasContent) {
496
+ alert("目前畫布是空的,無需清除。");
497
+ return;
498
+ }
499
+
500
+ if (confirm("確定要進行一鍵清空嗎?所有編輯的內容將會消失且無法復原。")) {
501
+ // 重置頁面內容但保留目前的網格設定
502
+ const rows = currentGrid.value.rows;
503
+ const cols = currentGrid.value.cols;
504
+ const totalCells = rows * cols;
505
+
506
+ pages.value = [
507
+ { id: 1, cells: createPageCells(0, rows, cols) },
508
+ { id: 2, cells: createPageCells(totalCells, rows, cols) }
509
+ ];
510
+
511
+ // Reset UI
512
+ selectedCellIndex.value = null;
513
+ inputBuffer.value = '';
514
+ alert("內容已清空!");
515
+ }
516
+ };
517
+
518
  // Helper to set cell content easily using 1-based Row/Col
519
  // Row: 1-8, Col: 1-6
520
  const setCell = (pageIndex, row, col, type, content, rotation = 0) => {
 
531
  }
532
  };
533
 
534
+ const exportProject = () => {
535
+ const projectData = {
536
+ version: '1.0',
537
+ timestamp: new Date().toISOString(),
538
+ grid: currentGrid.value,
539
+ pages: pages.value
540
+ };
541
+
542
+ const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(projectData));
543
+ const downloadAnchorNode = document.createElement('a');
544
+ downloadAnchorNode.setAttribute("href", dataStr);
545
+ downloadAnchorNode.setAttribute("download", "magic_origami_project.json");
546
+ document.body.appendChild(downloadAnchorNode); // required for firefox
547
+ downloadAnchorNode.click();
548
+ downloadAnchorNode.remove();
549
+ };
550
+
551
+ const triggerImport = () => {
552
+ if (fileInputRef.value) fileInputRef.value.click();
553
+ };
554
+
555
+ const importProject = (event) => {
556
+ const file = event.target.files[0];
557
+ if (!file) return;
558
+
559
+ const reader = new FileReader();
560
+ reader.onload = (e) => {
561
+ try {
562
+ const importedData = JSON.parse(e.target.result);
563
+
564
+ // Basic validation
565
+ if (!importedData.grid || !importedData.pages) {
566
+ throw new Error("Invalid project file format");
567
+ }
568
+
569
+ // Restore state
570
+ currentGrid.value = importedData.grid;
571
+ pages.value = importedData.pages;
572
+
573
+ // Reset UI
574
+ selectedCellIndex.value = null;
575
+ activePageId.value = 1;
576
+ viewMode.value = 'overview';
577
+
578
+ alert("專案匯入成功!");
579
+ } catch (err) {
580
+ console.error(err);
581
+ alert("讀取檔案失敗,請確認檔案格式正確。");
582
+ } finally {
583
+ // Reset input value to allow re-importing same file if needed
584
+ event.target.value = '';
585
+ }
586
+ };
587
+ reader.readAsText(file);
588
+ };
589
+
590
  const applyTemplate = (templateId) => {
591
  // 移除了 confirm() 對話框,直接套用模板
592
  try {
 
827
  updateSelectedCellText,
828
  applyIconToCell,
829
  clearCurrentCell,
830
+ clearAllContent, // Export new function
831
+ exportPDF,
832
+ exportProject,
833
+ triggerImport,
834
+ importProject,
835
+ fileInputRef
836
  };
837
  }
838
  }).mount('#app');