2025-01-07 旅行分帳應用程式-步驟08
好,回到比較簡單的目標 👇
我們先完成這個功能:
🔧 功能目標:顯示每位成員應付的金額(取代現在的「應付 $0」)
🧮 分帳計算邏輯簡化說明
- 每筆支出會由某位成員支付一筆金額。
- 所有支出總額,平均分配給所有人。
- 每個人「應付」的金額 = 平均金額 - 他實際支付的金額
- 「應付金額」為正,代表他還要付給其他人;為負代表他已經付比較多。
✅ 要做的步驟
- 計算所有人平均應付的金額。
- 計算每個人實際支出的總額。
- 計算每個人的應付金額 = 平均 - 實支。
- 顯示在 UI 上
{{ member.name }} <span>應付 $xx</span>
🛠️ 修改 script setup
代碼
在 <script setup>
區塊中加上這段:
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
| import { computed } from 'vue'
const memberOwedAmounts = computed(() => { const totalAmount = expenses.value.reduce((sum, e) => sum + e.amount, 0) const memberCount = members.value.length const avg = memberCount > 0 ? totalAmount / memberCount : 0
const actualPaidMap = {} members.value.forEach(m => actualPaidMap[m.name] = 0)
expenses.value.forEach(e => { if (actualPaidMap[e.member] !== undefined) { actualPaidMap[e.member] += e.amount } })
const result = {} for (const name in actualPaidMap) { result[name] = Math.round((avg - actualPaidMap[name]) * 100) / 100 }
return result })
|
👁️🗨️ 修改模板中的「應付 $0」
找到這段 HTML:
1
| {{ member.name }} <span class="owe">應付 $0</span>
|
改為:
1 2
| {{ member.name }} <span class="owe">應付 ${{ memberOwedAmounts[member.name] ?? 0 }}</span>
|
🧪 測試方式
- 新增三位成員,例如 A、B、C。
- 假設 A 支出 300。
- 平均每人要出 100 → A 應付 -200(已多付),B/C 應付 100。
要不要下一步再幫你把「應收」顯示為綠色、「應付」顯示為紅色?還是你想先這樣?
你可以這樣修改:
- 在
<template>
裡的「應付 $0」區塊改為動態顯示「應收 / 應付」
- 根據金額正負變化 class 來變色
- 在
<style scoped>
裡新增 .credit
和 .debt
樣式
✅ 修改 <template>
(成員清單那邊)
把這段:
1
| <span class="owe">應付 $0</span>
|
改成這段:
1 2 3
| <span :class="balanceClass(member.name)"> {{ balanceText(member.name) }} </span>
|
✅ 在 <script setup>
裡新增 balanceText 與 balanceClass:
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
| function getMemberBalance(name) { const paid = expenses.value .filter(e => e.member === name) .reduce((sum, e) => sum + e.amount, 0)
const total = expenses.value.reduce((sum, e) => sum + e.amount, 0) const average = members.value.length > 0 ? total / members.value.length : 0
return paid - average }
function balanceText(name) { const balance = getMemberBalance(name) if (balance > 0) return `應收 $${balance.toFixed(2)}` if (balance < 0) return `應付 $${Math.abs(balance).toFixed(2)}` return '結清' }
function balanceClass(name) { const balance = getMemberBalance(name) if (balance > 0) return 'credit' if (balance < 0) return 'debt' return '' }
|
✅ 在 <style scoped>
裡新增樣式:
1 2 3 4 5 6 7 8 9
| .credit { color: green; font-weight: bold; }
.debt { color: red; font-weight: bold; }
|
這樣就可以依照支出情況,讓成員旁邊顯示「應收 $」為綠色,「應付 $」為紅色,「結清」不加樣式。
如果你希望我幫你一起整合進整份 code,我也可以幫你貼上完整版 😄
要嗎?