| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 
 | <!-- weightTrackerApp.vue --><template>
 <div class="p-4 max-w-md mx-auto">
 <h1 class="text-2xl font-bold mb-4">體重追蹤器</h1>
 
 <!-- 輸入表單-->
 <form @submit.prevent="addRecord" class="space-y-2 mb-4">
 <div>
 <label>日期:</label>
 <input type="date" v-model="newRecord.date" />
 </div>
 <div>
 <label>體重(kg):</label>
 <input type="number" v-model.number="newRecord.weight" class="border px-2 py-1" required />
 </div>
 <button type="submit" class="bg-blue-500 text-white px-4 py-1 rounded">新增</button>
 </form>
 
 <!-- 清單-->
 <ul class="space-y-2 mb-6">
 <li v-for="(record, index) in sortedRecords" :key="record.id" class="flex justify-between items-center border p-2">
 <span>{{ record.date }} - {{ record.weight }}kg</span>
 <button @click="deleteRecord(record.id)" class="text-red-500">刪除</button>
 </li>
 </ul>
 
 <!-- 圖表 -->
 <canvas ref="chartCanvas" class="w-full h-64"></canvas>
 </div>
 </template>
 
 <script setup>
 import { ref, computed, onMounted, watch, nextTick } from 'vue'
 
 const newRecord = ref({
 date: '',
 weight: null,
 })
 
 const records = ref([])
 
 // 取得 chart DOM 元素
 const chartCanvas = ref(null)
 let weightChart = null
 
 // 初始化資料
 onMounted(() => {
 const saved = localStorage.getItem('weight-records')
 if (saved) {
 records.value = JSON.parse(saved)
 }
 renderChart()
 })
 
 // 監看資料變化自動存入 localStorage 並更新圖表
 watch(records, (newVal) => {
 localStorage.setItem('weight-records', JSON.stringify(newVal))
 nextTick(() => renderChart())
 }, { deep: true })
 
 const addRecord = () => {
 if (!newRecord.value.date || !newRecord.value.weight) return
 records.value.push({
 id: Date.now(),
 date: newRecord.value.date,
 weight: newRecord.value.weight,
 })
 newRecord.value = { date: '', weight: null }
 }
 
 const deleteRecord = (id) => {
 records.value = records.value.filter(r => r.id !== id)
 }
 
 const sortedRecords = computed(() => {
 return [...records.value].sort((a, b) => new Date(a.date) - new Date(b.date))
 })
 
 const renderChart = () => {
 if (!chartCanvas.value) return
 
 // 銷毀舊圖表
 if (weightChart) {
 weightChart.destroy()
 }
 
 const data = sortedRecords.value
 weightChart = new Chart(chartCanvas.value, {
 type: 'line',
 data: {
 labels: data.map(r => r.date),
 datasets: [{
 label: '體重 (kg)',
 data: data.map(r => r.weight),
 borderColor: 'rgba(59,130,246,1)',
 backgroundColor: 'rgba(59,130,246,0.2)',
 fill: true,
 tension: 0.2
 }]
 },
 options: {
 responsive: true,
 plugins: {
 title: {
 display: true,
 text: '體重變化圖'
 }
 },
 scales: {
 y: {
 beginAtZero: false
 }
 }
 }
 })
 }
 </script>
 
 |