2025-01-03 旅行分帳應用程式-步驟05
好的!我們現在來進行以下的更新:
✅ 你要的新功能改動摘要:
中間區域分成兩邊:
- 左邊:成員清單(原本就有)
- 右邊:支出紀錄列表
- 顯示:付款人、金額、支出項目名稱
- 每筆帳款旁邊有一個 ❌ 刪除按鈕
我幫你修改整個排版、資料結構,並加上支出清單與刪除功能。
🔧 Vue Template:更新後程式碼
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
| <template> <div class="app-container"> <!-- 上方標題 --> <div class="header"> <h1>旅遊分帳應用程式</h1> </div>
<!-- 中間:分成左右 --> <div class="middle-section"> <!-- 左:成員列表 --> <div class="member-list" ref="memberListRef"> <h2>分帳成員</h2> <ul> <li v-for="(member, index) in members" :key="index" @click="selectMember(index)" :class="{ selected: selectedMemberIndex === index }"> {{ member.name }} <span class="owe">應付 $0</span> <div v-if="selectedMemberIndex === index" class="add-expense-section"> <button class="btn small-btn" @click.stop="showAddExpense = true">➕ 新增支出款項</button> </div> </li> </ul> </div>
<!-- 右:帳款列表 --> <div class="expense-list"> <h2>支出清單</h2> <div v-if="expenses.length === 0">尚無支出紀錄</div> <ul v-else> <li v-for="(expense, index) in expenses" :key="index"> <strong>{{ expense.member }}</strong> 支出 <strong>${{ expense.amount }}</strong> - {{ expense.category }} <button class="btn delete-btn" @click="deleteExpense(index)">❌</button> </li> </ul> </div> </div>
<!-- 底部:新增成員 --> <div class="bottom-section"> <input v-model="newMemberName" class="member-input" placeholder="輸入成員姓名" @keyup.enter="addMember" /> <button class="btn add-btn" @click="addMember">➕ 新增成員</button> </div>
<!-- Modal: 新增支出款項 --> <div v-if="showAddExpense" class="modal-backdrop"> <div class="modal"> <h3>新增支出</h3> <label>支出項目:</label> <input list="category-options" v-model="selectedCategory" placeholder="輸入或選擇項目" /> <datalist id="category-options"> <option v-for="cat in expenseCategories" :key="cat" :value="cat" /> </datalist>
<label>金額:</label> <input v-model.number="expenseAmount" type="number" placeholder="輸入金額" />
<div class="modal-buttons"> <button class="btn confirm" @click="addExpense">確認</button> <button class="btn cancel" @click="showAddExpense = false">取消</button> </div> </div> </div> </div> </template>
|
🎯 Script 區
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
| <script setup> import { ref, nextTick } from 'vue'
const members = ref([]) const newMemberName = ref('') const memberListRef = ref(null) const selectedMemberIndex = ref(null) const showAddExpense = ref(false)
const expenseCategories = ref(['餐飲', '住宿', '門票', '交通', '其他']) const selectedCategory = ref('') const expenseAmount = ref(0)
const expenses = ref([])
function addMember() { const name = newMemberName.value.trim() if (name !== '' && !members.value.some(m => m.name === name)) { members.value.push({ name }) newMemberName.value = '' nextTick(() => { const el = memberListRef.value if (el) el.scrollTop = el.scrollHeight }) } }
function selectMember(index) { if (selectedMemberIndex.value === index) { selectedMemberIndex.value = null showAddExpense.value = false } else { selectedMemberIndex.value = index showAddExpense.value = false } }
function addExpense() { const member = members.value[selectedMemberIndex.value] const trimmedCategory = selectedCategory.value.trim()
if (member && trimmedCategory && expenseAmount.value > 0) { expenses.value.push({ member: member.name, category: trimmedCategory, amount: expenseAmount.value })
if (!expenseCategories.value.includes(trimmedCategory)) { expenseCategories.value.push(trimmedCategory) }
selectedCategory.value = '' expenseAmount.value = 0 showAddExpense.value = false } else { alert('請輸入有效的項目與金額') } }
function deleteExpense(index) { expenses.value.splice(index, 1) } </script>
|
💄 Style 更新(加上左右分欄)
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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| <style scoped> .app-container { max-width: 800px; margin: auto; font-family: Arial, sans-serif; display: flex; flex-direction: column; height: 100vh; justify-content: space-between; }
.header { font-size: 1.5em; font-weight: 600; color: #5e3a4a; text-align: center; padding: 10px; background-color: #f8e6e6; border-bottom: 2px solid #d16a7b; }
.middle-section { flex-grow: 1; display: flex; padding: 10px; gap: 10px; overflow-y: auto; }
.member-list, .expense-list { flex: 1; background: #fdfdfd; border: 1px solid #ddd; border-radius: 8px; padding: 10px; overflow-y: auto; }
.member-list ul, .expense-list ul { list-style: none; padding: 0; }
li { margin: 5px 0; background: #f8f8f8; padding: 8px; border-radius: 5px; display: flex; justify-content: space-between; align-items: center; }
.owe { color: red; }
.bottom-section { padding: 10px; background-color: #f8e6e6; border-top: 2px solid #d16a7b; display: flex; gap: 10px; align-items: center; justify-content: center; }
.member-input { flex: 1; min-width: 200px; padding: 10px; font-size: 16px; border-radius: 5px; border: 1px solid #ccc; }
.add-btn { padding: 10px 20px; }
.btn { background-color: #d16a7b; color: white; border: none; border-radius: 5px; cursor: pointer; }
.btn:hover { background-color: #b85967; }
.selected { background-color: #ffe6e6; }
.small-btn { margin-top: 8px; font-size: 14px; padding: 6px 10px; }
.delete-btn { background-color: #f44336; padding: 4px 8px; font-size: 14px; }
.modal-backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.4); display: flex; justify-content: center; align-items: center; }
.modal { background-color: white; padding: 20px; border-radius: 10px; min-width: 300px; text-align: center; box-shadow: 0 0 10px rgba(0,0,0,0.3); }
.modal input { width: 80%; padding: 8px; margin: 10px 0; border-radius: 5px; border: 1px solid #ccc; }
.modal-buttons { display: flex; justify-content: space-between; gap: 10px; } </style>
|
這樣畫面就會是左右分佈:
- 👈 左邊:成員清單(點選可新增支出)
- 👉 右邊:支出紀錄,每筆有付款人、金額、名稱、刪除按鈕
要不要我再幫你加上:
- 金額統計?
- 自動算出誰該付誰多少?
你先看看這版對不對勁,我再幫你擴充 💪