1 2 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 118 119 120 121 122
| <template> <div class="p-4 max-w-6xl mx-auto"> <h1 class="text-2xl font-bold mb-6 text-center">體重追蹤器</h1>
<!-- 雙欄式佈局:左 1/4,右 3/4 --> <div class="flex flex-col md:flex-row gap-6">
<!-- 左邊:輸入與清單,佔 1/4 --> <div class="md:w-1/4 space-y-4"> <!-- 表單 --> <form @submit.prevent="addRecord" class="space-y-2"> <div> <label class="block mb-1">日期:</label> <input type="date" v-model="newRecord.date" class="w-full border px-2 py-1 rounded" /> </div> <div> <label class="block mb-1">體重(kg):</label> <input type="number" v-model.number="newRecord.weight" class="w-full border px-2 py-1 rounded" required /> </div> <button type="submit" class="bg-blue-500 text-white px-4 py-1 rounded w-full">新增</button> </form>
<!-- 清單 --> <ul class="space-y-2"> <li v-for="(record, index) in sortedRecords" :key="record.id" class="flex justify-between items-center border p-2 rounded text-sm"> <span>{{ record.date }} - {{ record.weight }}kg</span> <button @click="deleteRecord(record.id)" class="text-red-500">刪除</button> </li> </ul> </div>
<!-- 右邊:圖表,佔 3/4 --> <div class="md:w-3/4"> <canvas ref="chartCanvas" class="w-full h-96"></canvas> </div>
</div> </div> </template>
<script setup> import { ref, computed, onMounted, watch, nextTick } from 'vue'
const newRecord = ref({ date: '', weight: null, })
const records = ref([])
const chartCanvas = ref(null) let weightChart = null
onMounted(() => { const saved = localStorage.getItem('weight-records') if (saved) { records.value = JSON.parse(saved) } renderChart() })
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>
|