」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 我如何建立 PeerSplit:一個免費的點對點費用分攤應用程式 — 從構思到發布僅需數週時間

我如何建立 PeerSplit:一個免費的點對點費用分攤應用程式 — 從構思到發布僅需數週時間

發佈於2024-11-07
瀏覽:491

我构建了 PeerSplit——一个免费的、点对点的 Splitwise 替代品——从想法到发布仅用了两周时间!

PeerSplit 是一款本地优先的应用程序,用于分配团体费用。它可以离线工作,100% 免费且私密,不需要注册或任何个人数据。

以下是我如何构建它以及我在此过程中学到的一切。

为何选择 PeerSplit?

我多年来一直依靠 Splitwise 来管理与朋友和室友的开支。但由于最近的每日交易限制和侵入性广告,它的使用变得令人沮丧。

我想要一个免费的、隐私优先的替代方案,不需要服务器来存储或同步数据。我不会相信第三方服务器的费用。

在完成了点对点、本地优先的项目(例如锻炼追踪器和无干扰写作应用程序)后,我意识到我可以应用相同的方法来分配费用。

PeerSplit 就这样诞生了。我开始设计应用程序。


使用 Nuxt 构建 UI Nuxt UI

我不擅长设计 UI。

几个月前,我不会想到我可以构建一个像 PeerSplit 一样精美的 UI(有些人甚至说它比 Splitwise 具有更好的用户体验)。

那么,我是如何做到的呢? Nuxt UI。

Nuxt UI 非常华丽,并且拥有令人惊叹的开发者体验 (DX)。

它还附带其他有用的 Nuxt 模块,如 @nuxt/icon、@nuxtjs/tailwindcss 和 @nuxtjs/colormode。

我所要做的就是选择一种主色,并且我拥有了将 PeerSplit 的 UI 整合在一起所需的所有组件(图标、深色模式和其他所有内容)。


cr-sqlite 用于本地同步?

对于本地数据存储和同步,我选择了 cr-sqlite,它基于 wa-sqlite 构建并使用 CRDT(无冲突复制数据类型)。

CRDT 非常适合点对点系统,因为它们会自动处理冲突,因此用户可以离线工作,并且当他们重新连接时,更改会无缝合并。

但是,cr-sqlite 本身不会通过网络同步更改。它仅提供用于导出和合并更改的 API。您需要在设备之间手动发送这些更改。


Gun.js 用于点对点同步?

为了处理安全的点对点同步,我使用了 Gun.js,它提供了点对点分布式图形数据库。

Gun 的gun.user API 让我可以为每个组创建加密节点。组的所有更改都存储在该节点上,并且仅与组成员同步,从而保持所有内容的私密性。

当用户执行操作时,我将从 cr-sqlite 导出的更改并将它们推送到节点。当用户重新上线时,Gun 会同步新的更改,让每个人都了解最新情况。

以高性能的方式实现这一点很棘手。欲了解更多详细信息,您可以在这里查看源代码。


简化债务?

Splitwise(现在是 PeerSplit)的一个很酷的功能是“简化债务”。

具体原理是这样的:如果A欠B,B欠C,A可以直接向C付款,以减少还款次数。

在PeerSplit中,我首先计算每个人的净余额。然后我对这些余额进行排序,并建议一项一项付款,每次至少使一个人的余额为零。

这种排序可确保每个人在其设备上看到相同的还款。

这不是 100% 最优(某些群体可能仍然有最多 n-1 笔付款),但在大多数情况下效果很好。

最佳解决方案的计算结果是指数级的,并且只能节省少量费用。所以这是简单性和速度的最佳权衡!

export const groupGetPayments = (group) => {
  const payments = [];
  const balances = Object.entries(groupGetBalances(group)).map(([a, b]) => [
    b,
    a,
  ]);
  balances.sort();
  let i = 0,
    j = balances.length - 1;
  while (i  balances[j][0]) {
      payments.push({
        from: balances[i][1],
        to: balances[j][1],
        value: round(balances[j][0]),
      });
      balances[i][0]  = balances[j][0];
      balances[j][0] = 0;
    } else {
      payments.push({
        from: balances[i][1],
        to: balances[j][1],
        value: round(-balances[i][0]),
      });
      balances[j][0]  = balances[i][0];
      balances[i][0] = 0;
    }
  }
  return payments;
};

渐进式网页应用

我希望 PeerSplit 能够作为离线应用程序运行,但我不想经历构建多个本机应用程序或处理在应用程序商店上发布它们的漫长过程的麻烦。因此,选择渐进式 Web 应用程序 (PWA) 是明智的选择。

PWA 结合了网络和移动应用程序的优点,允许用户将其安装在自己的设备上,同时仍然享受离线功能。

为了将我的 Nuxt 应用程序转换为 PWA,我使用了 vite-pwa。
我在 Figma 中设计了一个 SVG 徽标,并使用它通过 vite-pwa 的资产生成器生成所有必需的 PWA 资产。

之后,我配置了 PWA 清单,vite-pwa 会自动为我设置 Service Worker。

我将 Nuxt 配置为预渲染所有路线,以便我的应用程序可以完全离线运行。


这就结束了。感谢您的阅读!

产品搜索发布

PeerSplit 刚刚在 Product Hunt 上推出!这是我的第一次发布,希望得到您的支持和反馈。

查看 Product Hunt 上的 PeerSplit

PeerSplit 是公平来源的,因此请随意在 GitHub 上贡献或提交功能请求。

How I built PeerSplit: A free, peer-to-peer expense-splitting app—from idea to launch in just eeks 塔奈维克 / 同行分裂

PeerSplit 是一款免费、本地优先的点对点应用程序,可帮助您轻松、私密地分配和跟踪团体费用。

对等分裂​​

PeerSplit 是一款免费、本地优先的点对点应用程序,可帮助您轻松、私密地分配和跟踪团体费用。

特征

  • 100% 免费 — 无需注册
  • 本地优先 — 完全离线工作
  • 跨平台 PWA — 在移动设备、台式机或笔记本电脑上使用
  • 点对点 — 与朋友协作,同时保持数据私密性
  • 简单的用户体验 — 流畅且简约的界面,不妨碍您
  • 深色和浅色模式 — 在主题之间切换以符合您的喜好
  • 导入/导出 — 从 Splitwise 导入并将数据导出到 CSV

计划的功能

  • 高级账单拆分 — 添加明细账单作为单一费用。
  • 账单扫描 — 通过拍照自动扫描和拆分账单。
  • 多币种支持 — 通过实时汇率处理不同币种的费用。
  • 交易备注和评论 — 为每笔交易添加备注和评论以保留…


在 GitHub 上查看


版本聲明 本文轉載於:https://dev.to/tanay/how-i-built-peersplit-a-free-peer-to-peer-expense-splitting-app-from-idea-to-launch-in-just- 2-weeks-386m?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 有哪些資源可用於實現彗星模式?
    有哪些資源可用於實現彗星模式?
    Comet:伺服器推送模式伺服器推送是一種在伺服器和Web 用戶端之間實現雙向通訊的技術,已經獲得了顯著的成果最近的興趣。 Comet 設計模式是作為在 JavaScript 應用程式中實現伺服器推送的一種有前途的方法而出現。本問題探討了 Comet 模式的 jQuery 實作和通用資源的可用性。 ...
    程式設計 發佈於2024-11-07
  • 探索心理健康門診計畫的類型
    探索心理健康門診計畫的類型
    門診心理健康治療方法是一種不強調在醫療機構過夜的方案。這種療法主要在醫生辦公室、醫院或診所提供,在那裡人們可以進行定期治療,以進行高度結構化的定期治療。 在 COVID-19 大流行期間,全球約有 2.75 億名吸毒者。比前幾十年高出近 22%。吸毒成癮的增加導致全美吸毒過量人數創下歷史新高。好消...
    程式設計 發佈於2024-11-07
  • 如何在 C++ Builder 中初始化 OpenGL 幀:逐步指南
    如何在 C++ Builder 中初始化 OpenGL 幀:逐步指南
    如何在C Builder 中初始化OpenGL 幀在C Builder 中的窗體內初始化OpenGL 幀可能是一項具有挑戰性的任務。在嘗試調整現有 OpenGL 程式碼(例如問題中提供的範例)時,您可能會遇到困難。 要正確建立和渲染OpenGL 幀,請依照下列步驟操作:使用TForm::Handle...
    程式設計 發佈於2024-11-07
  • 利用這些罕見的 HTML 屬性來增強您的 Web 開發技能
    利用這些罕見的 HTML 屬性來增強您的 Web 開發技能
    Introduction HTML attributes are most often referred to as the overlooked heroes of web development, playing a crucial role in shaping the st...
    程式設計 發佈於2024-11-07
  • 如何在 Python 中將字串轉換為二進位:ASCII 與 Unicode?
    如何在 Python 中將字串轉換為二進位:ASCII 與 Unicode?
    在Python中將字串轉換為二進位在Python中,您可能會遇到需要將字串表示為二進位數字序列的情況。這對於多種原因都很有用,例如資料加密或二進位檔案操作。 使用 bin() 函數將字串轉換為二進位的最簡單方法就是使用bin()函數。該函數接受一個字串作為輸入,並將其二進位表示形式傳回為字串。例如:...
    程式設計 發佈於2024-11-07
  • 為什麼從 Java 中的匿名內部類別存取外部實例變數需要是 Final?
    為什麼從 Java 中的匿名內部類別存取外部實例變數需要是 Final?
    Java內部類別:為什麼必須使用「最終」外部實例變數在Java中定義匿名內部類別時,您可能會遇到將外部實例變數標記為“final”的要求。本文探討了這個約束背後的原因。 如同提供的程式碼中所提到的,實例變數 jtfContent 必須宣告為 Final 才能在內部類別中存取。這項要求源自於 Java...
    程式設計 發佈於2024-11-07
  • 理解 Python 中的關鍵字參數
    理解 Python 中的關鍵字參數
    When you're programming in Python, knowing how to pass arguments to functions is key for writing clear, flexible, and easy-to-maintain code. One powe...
    程式設計 發佈於2024-11-07
  • 如何防止列印時DIV跨頁分割?
    如何防止列印時DIV跨頁分割?
    列印問題:防止 DIV 跨頁分叉遇到動態 DIV 在頁面之間切成兩半的列印困境?當嘗試列印具有大量可變高度 DIV 元素的冗長文件時,就會出現此問題。 CSS 救援解決方案為了解決此問題,CSS 屬性打破了 -裡面來拯救。透過指定值避免,您可以確保渲染引擎防止 DIV 中途分割。這是程式碼片段:@m...
    程式設計 發佈於2024-11-07
  • Python 是強類型語言嗎?
    Python 是強類型語言嗎?
    Python 是強型別語嗎? Python 中的強型別概念造成了一些混亂,因為該語言允許變數改變執行期間的類型。然而,Python 確實是強型別的,儘管是動態的。 Python 中的強型別強型別可確保值維持其宣告的型別,除非明確轉換。在Python中,這意味著變數沒有固定的類型,而是它們所保存的值有...
    程式設計 發佈於2024-11-07
  • 購買亞馬遜評論
    購買亞馬遜評論
    https://dmhelpshop.com/product/buy-amazon-reviews/ 购买亚马逊评论 当谈到在亚马逊上进行商务和销售产品时,评论的重要性怎么强调都不为过。一条评论就可以决定购买的成败,而潜在的买家往往会犹豫是否购买缺乏评论的产品。缺乏评论可以起到威慑作用,这就是为什么...
    程式設計 發佈於2024-11-07
  • 使用 DTO 簡化 Laravel 中的資料傳輸
    使用 DTO 簡化 Laravel 中的資料傳輸
    這是如何使用 Laravel Data: 建立資料傳輸物件 (DTO) 的逐步範例 1. 安裝Laravel封包 首先,使用 Composer 安裝 spatie/laravel-data 套件。該軟體包有助於創建 DTO 並有效管理資料。 composer require spa...
    程式設計 發佈於2024-11-07
  • Go中如何找到與原始檔案相關的檔案?
    Go中如何找到與原始檔案相關的檔案?
    在Go中尋找相對於原始檔的檔案與解釋性語言不同,Go程式是經過編譯的,執行時不需要來源文件。因此,Ruby 中使用 __FILE__ 來相對於原始檔案定位檔案的概念在 Go 中並不適用。 相反,Go 提供了 runtime.Caller 函數,該函數會傳回呼叫時的檔名。彙編。但是,此資訊對於動態定位...
    程式設計 發佈於2024-11-07
  • 如何在 Python 中高效率地統計專案出現次數?
    如何在 Python 中高效率地統計專案出現次數?
    提高效率的 Python 中項目頻率計數計算清單中項目的出現次數是一項常見的程式設計任務。這個問題探討了在 Python 中解決此問題的更有效方法。 最初提供的程式碼雖然功能強大,但涉及到對清單進行兩次迭代,從而導致效能不佳。關鍵的挑戰在於找到一種 Pythonic 方法來計算專案出現次數,而無需重...
    程式設計 發佈於2024-11-07
  • 探索非同步 Deepgram API:使用 Python 進行語音轉文本
    探索非同步 Deepgram API:使用 Python 進行語音轉文本
    今天將探索用於將語音轉換為文字的 Deepgram API [轉錄]。無論是建立語音助理、轉錄會議還是創建語音控制應用程序,Deepgram 都讓入門變得比以往更容易。 什麼是 Deepgram? Deepgram 是一個強大的語音辨識平台,它使用先進的機器學習模型來即時轉錄音訊。...
    程式設計 發佈於2024-11-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3