一、 设计目标
1.1 提供记账功能
收入账单管理:系统应能够详细记录个人或家庭的各类收入来源,包括工资、投资收益、奖金等,并允许用户进行自定义分类和标签设置。
支出账单管理:用户应能够方便地录入和跟踪日常支出,如购物、餐饮、交通等,并支持自定义支出分类和备注功能。
1.2 财务管理现代化
表分析:提供各种报表和分析功能,如柱状图,饼图,折线图,帮助用户更好地了解自己的财务状况,制定合理的预算和理财计划。
二、设计内容
2.1 系统程序结构设计
OAProject/ (项目根目录)
│
├── .idea/ (IDE配置目录)
├── .cursor/ (编辑器相关目录)
│
├── manage.py (Django项目管理脚本)
├── account.sql (数据库SQL脚本)
├── requirments.txt (项目依赖列表)
├── temp.html (临时HTML文件)
│
├── OAProject/ (项目核心配置)
│ ├── __init__.py
│ ├── settings.py (项目配置)
│ ├── urls.py (主URL路由)
│ ├── asgi.py (ASGI配置)
│ ├── wsgi.py (WSGI配置)
│ └── __pycache__/ (Python缓存目录)
│
├── OAUser/ (核心应用)
│ ├── __init__.py
│ ├── admin.py (管理员配置)
│ ├── apps.py (应用配置)
│ ├── forms.py (表单定义)
│ ├── models.py (数据模型)
│ ├── tests.py (测试代码)
│ ├── urls.py (应用URL路由)
│ ├── views.py (视图函数)
│ ├── __pycache__/ (Python缓存目录)
│ │
│ ├── migrations/ (数据库迁移)
│ │ ├── __init__.py
│ │ ├── 0001_initial.py (初始迁移)
│ │ ├── 0002_auto_20220506_1554.py (迁移文件)
│ │ ├── 0003_auto_20220526_2203.py (迁移文件)
│ │ └── __pycache__/ (Python缓存目录)
│ │
│ └── static/ (静态资源)
│ └── login/ (登录相关静态资源)
│ ├── css/ (样式文件)
│ ├── js/ (JavaScript文件)
│ ├── image/ (图片资源)
│ └── font/ (字体资源)
│
└── templates/ (HTML模板)
└── login/ (登录相关模板)
├── __init__.py
├── chart.html (统计图表页面)
├── income.html (收入记录页面)
├── index.html (主页面)
├── login.html (登录页面)
├── pay.html (支出记录页面)
├── personal-info.html (个人信息页面)
├── register.html (注册页面)
├── update_income.html (修改收入记录页面)
└── update_pay.html (修改支出记录页面)
2.2 系统流程图
1. 用户登录模块
1.1 设计概述
用户登录模块是系统的入口,用于验证用户身份并授权访问系统功能。登录界面采用现代化的UI设计,包含用户名和密码输入框,支持表单验证。
1.2 数据模型
class Users(models.Model):
uid = models.AutoField(primary_key=True, auto_created=True)
uname = models.CharField(max_length=30)
upwd = models.CharField(max_length=30, unique=True)
usex = models.CharField(max_length=30)
uemail = models.EmailField()
utel = models.BigIntegerField()
1.3 表单设计
class UserForm(forms.Form):
uname = forms.CharField(label="用户名", max_length=128,
widget=forms.TextInput(attrs={'class': 'form-control',
'placeholder': "Username",
'autofocus': ''}))
upwd = forms.CharField(label="密码", max_length=256,
widget=forms.PasswordInput(attrs={'class': 'form-control',
'placeholder': "Password"}))
1.4 业务流程
- 表单提交处理:
def login(request): if request.session.get('is_login', None): # 不允许重复登录 return redirect('/index/') if request.method == 'POST': login_form = forms.UserForm(request.POST) if login_form.is_valid(): uname = login_form.cleaned_data.get('uname') upwd = login_form.cleaned_data.get('upwd') try: user = models.Users.objects.get(uname=uname) except: message = '用户不存在!' return render(request, 'login/login.html', locals()) if user.upwd == upwd: request.session['is_login'] = True request.session['user_uid'] = user.uid request.session['user_uname'] = user.uname return redirect('/index/') else: message = '密码不正确!' return render(request, 'login/login.html', locals()) login_form = forms.UserForm() return render(request, 'login/login.html', locals())
- 会话管理:
- 用户登录成功后,在会话中设置is_login、user_uid、user_uname变量
- 用户登出时清除会话数据
1.5 界面设计
2. 用户注册模块
2.1 设计概述
用户注册模块提供新用户账号创建功能,采集用户基本信息,进行数据验证,并创建用户账号。
2.2 表单设计
class RegisterForm(forms.Form):
gender = (
('male', "男"),
('female', "女"),
)
uname = forms.CharField(label="用户名", max_length=128,
widget=forms.TextInput(attrs={'class': 'form-control'}))
upwd1 = forms.CharField(label="密码", max_length=256,
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
upwd2 = forms.CharField(label="确认密码", max_length=256,
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
uemail = forms.EmailField(label="邮箱地址",
widget=forms.EmailInput(attrs={'class': 'form-control'}))
utel = forms.CharField(label="电话号码", max_length=128,
widget=forms.TextInput(attrs={'class': 'form-control'}))
usex = forms.ChoiceField(label='性别', choices=gender)
2.3 业务流程
- 表单验证与处理:
def register(request): if request.session.get('is_login', None): return redirect('/login/') if request.method == 'POST': register_form = forms.RegisterForm(request.POST) if register_form.is_valid(): uname = register_form.cleaned_data.get('uname') upwd1 = register_form.cleaned_data.get('upwd1') upwd2 = register_form.cleaned_data.get('upwd2') uemail = register_form.cleaned_data.get('uemail') utel = register_form.cleaned_data.get('utel') usex = register_form.cleaned_data.get('usex') if upwd1 != upwd2: message = '两次输入的密码不同!' return render(request, 'login/register.html', locals()) same_name_user = models.Users.objects.filter(uname=uname) if same_name_user: message = '用户名已经存在' return render(request, 'login/register.html', locals()) same_email_user = models.Users.objects.filter(uemail=uemail) if same_email_user: message = '该邮箱已经被注册了!' return render(request, 'login/register.html', locals()) models.Users.objects.create(uname=uname, upwd=upwd1, uemail=uemail, utel=utel, usex=usex) return redirect('/login/') return render(request, 'login/register.html', locals()) register_form = forms.RegisterForm() return render(request, 'login/register.html', locals())
- 数据验证规则:
- 两次密码输入必须一致
- 用户名不可重复
- 邮箱地址不可重复
- 表单字段有效性验证
2.4 界面设计
3. 个人中心模块
3.1 设计概述
个人中心模块允许用户查看和修改个人信息,提供友好的信息展示和编辑界面。
3.2 业务流程
- 信息展示:
def personal(request): uid_nums = request.session['user_uid'] user_list = Users.objects.get(uid=uid_nums); return render(request, 'login/personal-info.html', { "user": user_list, })
- 信息更新:
@transaction.atomic def UpdatePro(request): """接收参数""" uame = request.GET.get('uname') upwd = request.GET.get('upwd') uemail = request.GET.get('uemail') utel = request.GET.get('utel') try: user = Users.objects.filter(uname__exact=uame).first() user.uname = uame user.upwd = upwd user.uemail = uemail user.utel = utel user.save() except DatabaseError as e: print(e) return redirect("/personal/")
3.3 界面设计
4. 首页模块
4.1 设计概述
首页是用户登录成功后的主界面,提供系统功能的入口和快速访问,展示系统的主要功能模块。
4.2 业务流程
def index(request):
if not request.session.get('is_login', None):
return redirect('/login/')
return render(request, 'login/index.html')
4.3 界面设计
5. 收入记账管理模块
5.1 设计概述
收入记账管理模块提供收入记录的增删改查功能,支持分页和搜索,便于用户管理收入数据。
5.2 数据模型
class Income(models.Model):
iId = models.AutoField(primary_key=True)
iType = models.CharField(max_length=30) # 类型(借入、收入)
iMoney = models.DecimalField(max_digits=10, decimal_places=2) # 金额
iRemark = models.CharField(max_length=55) # 备注
iTime = models.DateField() # 时间
5.3 表单设计
class IncomeForm(forms.Form):
iType = forms.CharField(label="类型", max_length=30) # 类型(借入、收入)
iMoney = forms.DecimalField(label="金额", max_digits=10, decimal_places=2) # 金额
iRemark = forms.CharField(label="备注", max_length=55) # 备注
iTime = forms.DateField(label="时间") # 时间
5.4 业务流程
- 添加收入记录:
def insertRecord(request): if not request.session.get('is_login', None): return redirect('/login/') income_form = forms.IncomeForm(request.POST) if income_form.is_valid(): iType = income_form.cleaned_data.get('iType') iMoney = income_form.cleaned_data.get('iMoney') iRemark = income_form.cleaned_data.get('iRemark') iTime = income_form.cleaned_data.get('iTime') if iType == "收入": models.Income.objects.create(iType=iType, iMoney=iMoney, iRemark=iRemark, iTime=iTime) else: models.Pay.objects.create(pType=iType, pMoney=iMoney, pRemark=iRemark, pTime=iTime) if iType == "收入": return redirect('/income') else: return redirect('/pay')
- 查看收入记录:
def income(request): if not request.session.get('is_login', None): return redirect('/login/') key = request.GET.get("key") if key is None: new_list = Income.objects.all() else: new_list = Income.objects.filter(iRemark__contains=key) page = request.GET.get("page") if page is None: page = 1 else: page = int(page) page_count = (len(new_list) - 1) // 10 + 1 page_count = range(1, page_count + 1) new_list = new_list[page * 10 - 10: page * 10] return render(request, 'login/income.html', locals())
- 更新收入记录:
def update_income(request): update_id = request.GET.get("iId") if request.method == "POST": new_type = request.POST.get('iType') new_money = request.POST.get('iMoney') new_remark = request.POST.get('iRemark') new_time = request.POST.get('iTime') update_obj = models.Income.objects.get(iId=update_id) update_obj.iType = new_type update_obj.iMoney = new_money update_obj.iRemark = new_remark update_obj.iTime = new_time update_obj.save() return redirect('/income/') ret = models.Income.objects.get(iId=update_id) return render(request, 'login/update_income.html', {'ret': ret})
- 删除收入记录:
def del_income(request): income_id = request.GET.get("iId") models.Income.objects.filter(iId=income_id).delete() return redirect('/income/')
5.5 界面设计
6. 支出记账管理模块
6.1 设计概述
支出记账管理模块提供支出记录的增删改查功能,支持分页和搜索,便于用户管理支出数据。
6.2 数据模型
class Pay(models.Model):
pId = models.AutoField(primary_key=True)
pType = models.CharField(max_length=30) # 类型(借出、支出)
pMoney = models.DecimalField(max_digits=10, decimal_places=2) # 金额
pRemark = models.CharField(max_length=55) # 备注
pTime = models.DateField() # 时间
6.3 表单设计
class PayForm(forms.Form):
pType = forms.CharField(label="类型", max_length=30) # 类型(借出、支出)
pMoney = forms.DecimalField(label="金额", max_digits=10, decimal_places=2) # 金额
pRemark = forms.CharField(label="备注", max_length=55) # 备注
pTime = forms.DateField(label="时间") # 时间
6.4 业务流程
- 查看支出记录:
def pay(request): if not request.session.get('is_login', None): return redirect('/login/') key = request.GET.get("key") if key is None: new_list1 = Pay.objects.all() else: new_list1 = Pay.objects.filter(pRemark__contains=key) page = request.GET.get("page") if page is None: page = 1 else: page = int(page) page_count = (len(new_list1) - 1) // 10 + 1 page_count = range(1, page_count + 1) new_list1 = new_list1[page * 10 - 10: page * 10] return render(request, 'login/pay.html', locals())
- 更新支出记录:
def update_pay(request): edit_id = request.GET.get("pId") if request.method == "POST": new_ptype = request.POST.get('pType') new_pmoney = request.POST.get('pMoney') new_premark = request.POST.get('pRemark') new_ptime = request.POST.get('pTime') edit_obj = models.Pay.objects.get(pId=edit_id) edit_obj.pType = new_ptype edit_obj.pMoney = new_pmoney edit_obj.pRemark = new_premark edit_obj.pTime = new_ptime edit_obj.save() return redirect('/pay/') reet = models.Pay.objects.get(pId=edit_id) return render(request, 'login/update_pay.html', {'reet': reet})
- 删除支出记录:
def del_pay(request): pay_id = request.GET.get("pId") models.Pay.objects.filter(pId=pay_id).delete() return redirect('/pay/')
6.5 界面设计
7. 记账图表模块
7.1 设计概述
记账图表模块通过可视化图表展示用户的收支情况,包括最近15天的收支柱状图和收支分布饼图,帮助用户直观了解财务状况。
7.2 业务流程
def chart(request):
if not request.session.get('is_login', None):
return redirect('/login/')
# 横坐标,表示日期
x = []
# 纵坐标
y1 = []
y2 = []
i_dir = {}
p_dir = {}
# 返回当前时间的时间戳(1970纪元后经过的浮点秒数)
time_sprite = time.time()
time_sprite -= 14 * 24 * 60 * 60
for i in range(15):
# 得到当前的年月日信息
local = time.localtime(time_sprite)
year = local.tm_year
month = local.tm_mon
day = local.tm_mday
date_str = "%d-%02d-%02d" % (year, month, day)
i_dir[date_str] = 0
p_dir[date_str] = 0
# 日期一天天叠加
x.append(date_str)
time_sprite += 24 * 60 * 60
# 获取收入表里面的所有信息
income_list = Income.objects.all()
for item in income_list:
time_str = str(item.iTime)
# 判断收入日期是否在最近15天内,若在,则计算当天收入金额总和
if time_str in i_dir:
i_dir[time_str] += item.iMoney
# 获取支出表里面的所有信息
pay_list = Pay.objects.all()
for item in pay_list:
time_str = str(item.pTime)
# 判断支出日期是否在最近15天内,若在,则计算当天支出金额总和
if time_str in p_dir:
p_dir[time_str] += item.pMoney
for day in x:
y1.append(float(i_dir[day]))
y2.append(float(p_dir[day]))
# 计算总收入和总支出
total_income = sum(y1)
total_expense = sum(y2)
balance = total_income - total_expense
# 创建柱状图和饼图...
# 省略图表创建代码...
return render(request, 'login/chart.html', {
'bar_chart': bar_chart,
'pie_chart': pie_chart_html,
'x': x,
'y1': y1,
'y2': y2,
'total_income': total_income,
'total_expense': total_expense,
'balance': balance,
})
7.3 图表设计
总结
个人记账系统是一个完整的Web应用,提供了用户认证、个人信息管理、记账管理和数据可视化等功能。系统采用Django框架开发,前端使用现代化UI设计,后端实现了完整的数据处理逻辑。系统具有良好的用户体验,帮助用户有效管理个人财务信息。
视频演示
20250511_135255