作为每天都要记收支的“月光族”,一直想要个轻量化记账工具——不用注册账号,数据存在自己电脑里,打开浏览器就能用。原本以为要学后端、配数据库,没想到用**CodeBuddy**辅助,单靠HTML+前端技术就搞定了本地SQLite记账本!从需求梳理到代码落地只花了1.5小时,今天把这份超详细教程分享出来,代码逐行解释,小白跟着做也能成。

一、先吹爆CodeBuddy:前端小白也能玩转本地数据库!

最开始我只懂点基础HTML/CSS,对“前端操作SQLite”完全没概念,是CodeBuddy帮我打通了所有关键环节:
- 我刚说“想用HTML做记账本,数据存在本地”,它立刻推荐用`sql.js`(前端SQLite库),还解释“不用装后端,浏览器直接读写字节流,数据能导出备份”;
- 写数据库初始化代码时,我忘了“创建表后默认插入分类数据”,CodeBuddy直接补全`INSERT`语句,还标注“提前加好‘餐饮’‘工资’等分类,用户不用手动输”;
- 做收支统计时,我纠结“怎么按月份分组计算”,它不光生成`GROUP BY`SQL,还帮我写了日期格式化函数,连“空数据时显示‘暂无记录’”的兼容逻辑都考虑到了;
- 甚至UI布局,我只说“想要简洁点,分输入区和列表区”,它直接给了响应式代码,还提醒“加个导出按钮,防止浏览器缓存丢失数据”。
简单说:有了CodeBuddy,不用再到处查“前端怎么连SQLite”“怎么处理本地数据”,它会把复杂技术拆成简单代码,还帮你补全所有细节,开发效率至少翻4倍!
二、项目核心技术栈
全程不用后端,纯前端+本地数据库,环境准备超简单:
- **基础框架**:HTML(结构)+ Tailwind CSS(样式,不用写原生CSS);
- **本地数据库**:`sql.js`(前端操作SQLite的库,浏览器直接运行,不用装任何服务);
- **交互逻辑**:JavaScript(处理表单提交、数据库操作、数据渲染);
- **辅助工具**:CodeBuddy(梳理需求、生成核心代码、补全兼容逻辑、优化用户体验)。
- **环境准备:** 只要有个浏览器(Chrome/Firefox都行)+ IDE编辑器(CodeBuddy最佳),不用装任何插件——`sql.js`直接用CDN引入,Tailwind CSS也是CDN加载,打开HTML文件就能跑。
三、开发步骤:从0到1搭本地记账本
Prompt:我们把开发拆成5步:引入依赖→初始化本地SQLite→写记账表单→实现CRUD功能→加数据导出/统计,每一步都附CodeBuddy生成的代码+详细解释。

步骤1:引入核心依赖(3行代码搞定)
首先在HTML头部引入`sql.js`(前端SQLite库)和Tailwind CSS(样式库),不用下载文件,直接用CDN链接——这步CodeBuddy帮我找好了最新稳定版链接,避免踩“版本兼容”坑:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CodeBuddy·本地SQLite记账本</title>
<!-- 1. 引入Tailwind CSS(快速写样式,不用写原生CSS) -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 2. 引入sql.js(前端操作SQLite的核心库) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js"></script>
<!-- 3. 配置Tailwind自定义颜色(记账本主色调:蓝色系) -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#165DFF', // 主色(按钮、标题)
secondary: '#E8F3FF', // 辅助色(表单背景)
danger: '#FF4D4F', // 危险色(删除按钮)
},
}
}
}
</script>
</head>
<body class="bg-gray-50 min-h-screen p-4 md:p-8">
<!-- 后面的内容写这里 -->
</body>
</html>
CodeBuddy的贴心细节:
- 加了`viewport` meta标签:确保在手机上打开也是响应式的,不会出现横向滚动条;
- 自定义Tailwind颜色:统一记账本风格,后续写按钮、表单不用反复调色值;
- 选的`sql.js`版本是1.8.0稳定版:避免用最新版踩兼容性坑,还标注了“wasm版性能更好”。
步骤2:初始化本地SQLite数据库
接下来要创建本地SQLite数据库文件(注意:前端无法直接写本地文件,`sql.js`是把数据库存在浏览器内存+通过导出功能存到本地),先建“收支记录表”和“分类表”——这步CodeBuddy帮我设计了表结构,还加了“初始化默认分类”的逻辑:
<body>
<!-- 页面内容先空着,先写数据库初始化逻辑 -->
<script>
// 1. 初始化SQLite数据库(CodeBuddy帮我写的核心函数)
let db; // 数据库实例(全局变量,后续操作都用它)
async function initDB() {
try {
// 加载sql.js的WASM文件(必须异步,确保加载完成)
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/${file}`
});
// 两种初始化方式:① 空数据库 ② 加载本地导出的数据库(恢复数据)
// 先创建空数据库,后续加“导入”功能
db = new SQL.Database();
console.log("SQLite数据库初始化成功!");
// 2. 创建表结构(收支记录表+分类表)
// 分类表:提前定义收支分类,避免用户重复输入
db.run(`
CREATE TABLE IF NOT EXISTS categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE, -- 分类名(如“餐饮”“工资”)
type TEXT NOT NULL -- 类型(收入/支出)
);
`);
// 收支记录表:核心表,存每条记账数据
db.run(`
CREATE TABLE IF NOT EXISTS records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL, -- 记账日期(YYYY-MM-DD)
category_id INTEGER NOT NULL, -- 关联分类表的ID
amount REAL NOT NULL, -- 金额(支持小数)
remark TEXT, -- 备注(可选)
FOREIGN KEY (category_id) REFERENCES categories(id) -- 外键关联,确保分类有效
);
`);
// 3. 初始化默认分类(如果分类表为空)
const categoryCount = db.get(`SELECT COUNT(*) AS count FROM categories;`).count;
if (categoryCount === 0) {
// 收入分类
db.run(`INSERT INTO categories (name, type) VALUES ('工资', '收入');`);
db.run(`INSERT INTO categories (name, type) VALUES ('兼职', '收入');`);
db.run(`INSERT INTO categories (name, type) VALUES ('理财收益', '收入');`);
// 支出分类
db.run(`INSERT INTO categories (name, type) VALUES ('餐饮', '支出');`);
db.run(`INSERT INTO categories (name, type) VALUES ('房租', '支出');`);
db.run(`INSERT INTO categories (name, type) VALUES ('交通', '支出');`);
db.run(`INSERT INTO categories (name, type) VALUES ('购物', '支出');`);
console.log("默认分类初始化完成!");
}
// 4. 初始化完成后,加载已有记账记录
loadRecords();
// 加载分类到下拉框
loadCategories();
} catch (error) {
console.error("数据库初始化失败:", error);
alert("记账本加载失败,请刷新页面重试!");
}
}
// 2. 加载分类到下拉框(供用户选择)
function loadCategories() {
// 清空现有选项(避免重复)
const categorySelect = document.getElementById("category");
categorySelect.innerHTML = '<option value="">请选择分类</option>';
// 监听收支类型切换,加载对应分类
const typeSelect = document.getElementById("recordType");
const selectedType = typeSelect.value;
// 查询对应类型的分类
const categories = db.all(`
SELECT id, name FROM categories WHERE type = ? ORDER BY name;
`, [selectedType]);
// 填充下拉框
categories.forEach(cat => {
const option = document.createElement("option");
option.value = cat.id;
option.textContent = cat.name;
categorySelect.appendChild(option);
});
}
// 页面加载完成后初始化数据库
window.onload = initDB;
</script>
</body>
代码解释(CodeBuddy帮我标红的关键逻辑):
- `initSqlJs`异步加载:WASM文件必须异步加载,否则会报错,CodeBuddy帮我处理了异步逻辑;
- 外键关联`FOREIGN KEY`:确保收支记录的分类一定存在,避免无效数据;
- 默认分类初始化:判断分类表为空才插入,避免重复添加;
- 分类加载联动:根据用户选择的“收入/支出”类型,动态加载对应分类,用户体验更好。
步骤3:写记账表单(HTML+Tailwind样式)
有了数据库,接下来做用户交互的表单——要能选日期、收支类型、分类,输入金额和备注。CodeBuddy帮我写了响应式表单,还加了“日期默认今天”“金额校验”的细节:
<body>
<!-- 页面标题 -->
<div class="max-w-4xl mx-auto mb-8">
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-primary text-center">
本地SQLite记账本
</h1>
<p class="text-gray-500 text-center mt-2">数据存本地,安全不泄露 | 支持导出备份</p>
</div>
<!-- 1. 记账表单 -->
<div class="max-w-4xl mx-auto bg-white rounded-lg shadow-md p-6 mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4">添加收支记录</h2>
<form id="recordForm" class="grid grid-cols-1 md:grid-cols-3 gap-4">
<!-- 日期选择 -->
<div class="col-span-1">
<label for="date" class="block text-sm font-medium text-gray-700 mb-1">日期</label>
<input
type="date"
id="date"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50"
required
>
</div>
<!-- 收支类型 -->
<div class="col-span-1">
<label for="recordType" class="block text-sm font-medium text-gray-700 mb-1">类型</label>
<select
id="recordType"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50"
required
onchange="loadCategories()" <!-- 切换类型时重新加载分类 -->
>
<option value="收入">收入</option>
<option value="支出">支出</option>
</select>
</div>
<!-- 分类选择(动态加载) -->
<div class="col-span-1">
<label for="category" class="block text-sm font-medium text-gray-700 mb-1">分类</label>
<select
id="category"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50"
required
>
<option value="">请选择分类</option>
</select>
</div>
<!-- 金额输入 -->
<div class="col-span-1">
<label for="amount" class="block text-sm font-medium text-gray-700 mb-1">金额(元)</label>
<input
type="number"
id="amount"
step="0.01"
min="0.01"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50"
required
placeholder="请输入金额"
>
</div>
<!-- 备注输入 -->
<div class="col-span-2">
<label for="remark" class="block text-sm font-medium text-gray-700 mb-1">备注(可选)</label>
<input
type="text"
id="remark"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50"
placeholder="例如:早餐买包子、5月工资"
>
</div>
<!-- 提交按钮 -->
<div class="col-span-3 text-right">
<button
type="submit"
class="px-6 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors focus:outline-none focus:ring-2 focus:ring-primary/50"
>
保存记账记录
</button>
</div>
</form>
</div>
<!-- 后面加记录列表和统计区域 -->
<!-- 数据库初始化脚本(前面写的initDB等代码) -->
<script>
// 先给日期输入框设置默认值为今天
document.getElementById("date").valueAsDate = new Date();
// 表单提交事件(添加记账记录)
document.getElementById("recordForm").addEventListener("submit", function(e) {
e.preventDefault(); // 阻止表单默认提交
// 获取表单数据
const date = document.getElementById("date").value;
const categoryId = document.getElementById("category").value;
const amount = parseFloat(document.getElementById("amount").value);
const remark = document.getElementById("remark").value || "";
try {
// 插入数据库
db.run(`
INSERT INTO records (date, category_id, amount, remark)
VALUES (?, ?, ?, ?);
`, [date, categoryId, amount, remark]);
// 提示成功并重置表单
alert("记账成功!");
this.reset(); // 重置表单
document.getElementById("date").valueAsDate = new Date(); // 重新设置默认日期
loadRecords(); // 刷新记录列表
} catch (error) {
console.error("添加记录失败:", error);
alert("记账失败,请重试!");
}
});
// (前面的initDB、loadCategories函数写在这里)
</script>
</body>
CodeBuddy的优化细节:
- 响应式布局:用Tailwind的`grid`和`col-span`,手机上表单垂直排列,电脑上横向排列,适配所有设备;
- 表单校验:加了`required`、`min="0.01"`、`step="0.01"`,确保金额是正数且有两位小数;
- 默认日期:页面加载时自动给日期框填今天,不用用户手动选;
- 分类联动:切换“收入/支出”时,通过`onchange="loadCategories()"`动态更新分类下拉框,避免用户选到无效分类。
运行效果
几分钟 一个html项目就完成了!是不是 soeasy!!

四、使用说明:打开就能用,数据不丢失
1. **运行方式**:把上面代码保存为`account-book.html`,双击文件用Chrome/Firefox打开,直接进入记账界面;
2. **核心功能**:
- 加记录:选日期、类型、分类,输金额备注,点“保存”;
- 查记录:表格显示所有记录,可按日期筛选;
- 改/删记录:选中记录点“修改”(弹窗改数据)或“删除”(需确认);
- 备份数据:点“导出数据库”,下载`.db`文件,下次想恢复时(后续可加导入功能,CodeBuddy也能生成);
3. **数据安全**:数据存在浏览器内存,关闭页面后不会丢(浏览器缓存保留),但换浏览器/清缓存会丢,所以一定要定期导出备份!
五、总结:CodeBuddy让前端开发门槛直接消失!
这次开发最大的感受是:CodeBuddy完全懂“新手需要什么”——我不用学`sql.js`的复杂API,不用记Tailwind的类名,甚至不用想“用户会怎么操作”,它会把所有复杂逻辑拆成简单代码,还帮你补全所有细节:
- 我没想到“前端连SQLite”,它推荐`sql.js`还写好初始化代码;
- 我忘了“分类要和收支类型联动”,它主动加了`onchange`事件;
- 我没考虑“数据备份”,它直接生成导出功能,还提醒“文件名带日期”。
对新手来说,这不仅能快速做出能用的工具,还能从代码里学规范(比如SQL关联查询、响应式布局);对熟手来说,省掉查文档、写重复代码的时间,专注做核心功能。如果你也想快速开发小工具,强烈试试CodeBuddy——它真的能让你从“卡代码”变成“顺顺利利做成品”,开发体验直接拉满!


