购物车+ATM项目(图形化)
阅读原文时间:2023年07月08日阅读:2

项目下载

项目目录结构

运行效果





seetings.py

import logging
import logging.config
# 定义日志输出格式 开始
import os

standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'  # 其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

self_format = '[%(asctime)s][%(name)s][%(message)s]'
# 定义日志输出格式 结束

# 自定义文件路径
logfile_path = os.path.join(os.path.abspath('log'), 'a.log')

# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': self_format
        },
        'simple': {
            'format': self_format
        },
    },
    'filters': {},  # 过滤日志
    'handlers': {
        # 打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,  # 日志文件
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        }, 

    },
}
}

business.py

import hashlib
import os
import json
import tkinter
from core import win_login
from lib import common

db_path = os.path.abspath('db')

def open_file_read(path):
    with open(path) as f1:
        user_dict = json.load(f1)
        return user_dict

def open_file_write(path, user_dict):
    with open(path, 'w') as f1:
        json.dump(user_dict, f1)

# 注册
def register(*args, **kwargs):
    # 获取用户名和密码
    a = 0
    name = args[0]
    pwd = args[1]
    pwd_again = args[2]
    # 判断两次密码是否一致,不一致提醒用户
    if pwd_again != pwd:
        print('------两次密码不一致------')
        a = 1
        return a
    # 使用os.path.join方法拼出存储用户信息的文件路径
    user_file_path = os.path.join(db_path, f'{name}.json')
    # 该用户文件存在,则提醒用户
    if os.path.exists(user_file_path):
        print('------用户已经存在------')
        a = 2
        return a
    # 初始化用户数据
    md5 = hashlib.md5()
    md5.update(f'{name}用户的密码是{pwd}'.encode('utf8'))  # 动态加盐
    res = md5.hexdigest()
    user_dict = {'name': name, 'pwd': res, 'balance': 15000, 'shop_car': {}}
    # 将用户数据写入文件
    open_file_write(user_file_path, user_dict)
    print(f'------用户 {name} 注册成功------')
    return a

# 登入
def login(*args, **kwargs):
    # 获取用户名和密码
    a = 0
    name = args[0]
    pwd = args[1]
    # 使用os.path.join方法拼出存储用户信息的文件路径
    user_file_path = os.path.join(db_path, f'{name}.json')
    # 判断数据库中是否有这个用户的数据,没有则提示用户
    if not os.path.exists(user_file_path):
        print('------用户不存在------')
        a = 1
        return a
    # 将数据从文件中转成原数据格式
    user_dict = open_file_read(user_file_path)
    # 判断用户输入的密码是否正确
    md5 = hashlib.md5()
    md5.update(f'{name}用户的密码是{pwd}'.encode('utf8'))
    res = md5.hexdigest()
    if res == user_dict['pwd']:
        print('------登入成功------')
    else:
        print('------账号或密码错误------')
        a = 2
    return a

def add_shop_car(*args):
    good_list = [
        ['挂壁面', 3],
        ['印度飞饼', 22],
        ['极品木瓜', 666],
        ['土耳其土豆', 999],
        ['伊拉克拌面', 1000],
        ['董卓戏张飞公仔', 2000],
        ['仿真玩偶', 10000]
    ]
    # 创建一个临时的购物车
    shop_char = {}
    # 获取用户输入的编号
    chioce = args[0]
    # 如果用户输入的是商品编号,则准备开始添加
    if int(chioce) in range(len(good_list)):
        # 将商品名和单价分别取出来,放如两个变量
        good_list_list = good_list[int(chioce)]
        good_list_name = good_list_list[0]
        good_list_money = good_list_list[1]
        numb = int(args[1])
        if good_list_name in shop_char.keys():
            # 购物车中已经有该商品,则添加数量
            shop_char[good_list_name][0] += numb
        else:
            # 购物车没这个商品也就是第一次添加,则向零时购物车中新增键值对
            shop_char[good_list_name] = [numb, good_list_money]
    user_file_path = os.path.join(db_path, '%s.json' % args[2])
    user_dict = open_file_read(user_file_path)
    # 判断用户原来的购物车中是否有东西,有就增加,没有就添加新的键值对
    for name in shop_char.keys():
        if name in user_dict['shop_car'].keys():
            user_dict['shop_car'][name][0] += shop_char[name][0]
        else:
            user_dict['shop_car'][name] = shop_char[name]
    # 将用户信息重写回文件
    open_file_write(user_file_path, user_dict)
    tkinter.messagebox.showinfo(title='Hi', message='添加成功')

def to_money(*args):
    to_name_path = os.path.join(db_path, '%s.json' % args[1])
    self_ptah = os.path.join(db_path, '%s.json' % args[0])
    user_dict = open_file_read(self_ptah)
    shengyu = user_dict['balance'] - int(args[2])
    if os.path.exists(to_name_path):
        if user_dict['balance'] > int(args[2]):
            user_dict['balance'] -= int(args[2])
            open_file_write(self_ptah, user_dict)
            user_dict1 = open_file_read(to_name_path)
            user_dict1['balance'] += int(args[2])
            open_file_write(to_name_path, user_dict1)
            tkinter.messagebox.showinfo(title='Hi', message=f'转账成功,转出:{args[2]}元,剩余:{shengyu}')
            logger1 = common.get_logger(f'{args[0]}向{args[1]}转账了{args[2]}元')
            logger1.debug('转账业务')
        else:
            tkinter.messagebox.showinfo(title='Hi', message='余额不足')
    else:
        tkinter.messagebox.showinfo(title='Hi', message='用户不存在')

win_login.py

import os
import tkinter
from core import business
from tkinter import *
from lib import common
from core import business

is_login = {
    'username': None
}

def out_login(*args):
    is_login['username'] = None
    args[0].destroy()
    args[1].destroy()

def out_shop_chr(shop):
    shop.destroy()

def add_shop_chr(*args):
    business.add_shop_car(*args)

def add_shop():
    shop = tkinter.Toplevel()
    sw = shop.winfo_screenwidth()
    sh = shop.winfo_screenheight()
    shop.geometry("%dx%d+%d+%d" % (500, 500, (sw - 500) / 2, (sh - 650) / 2))
    good_list = [
        ['挂壁面', 3],
        ['印度飞饼', 22],
        ['极品木瓜', 666],
        ['土耳其土豆', 999],
        ['伊拉克拌面', 1000],
        ['董卓戏张飞公仔', 2000],
        ['仿真玩偶', 10000]
    ]
    shop_list = tkinter.Listbox(shop, selectmode=MULTIPLE, width=400, height=300)
    for item in ['商品编号:0 | 商品名:挂壁面   | 商品单价:3',
                 '商品编号:1 | 商品名:印度飞饼   | 商品单价:22',
                 '商品编号:2 | 商品名:极品木瓜   | 商品单价:666',
                 '商品编号:3 | 商品名:土耳其土豆   | 商品单价:999',
                 '商品编号:4 | 商品名:伊拉克拌面   | 商品单价:1000',
                 '商品编号:5 | 商品名:董卓戏张飞公仔   | 商品单价:2000',
                 '商品编号:6 | 商品名:仿真玩偶   | 商品单价:10000']:
        shop_list.insert(END, item)
    shop_list.pack()
    id = tkinter.StringVar()
    id_label = tkinter.Label(shop, text='请输入编号:').place(x=100, y=350)
    id_Entry = tkinter.Entry(shop, textvariable=id).place(x=200, y=350)

    numb = tkinter.StringVar()
    numb_label = tkinter.Label(shop, text='请输入数量: ').place(x=100, y=400)
    numb_Entry = tkinter.Entry(shop, textvariable=numb).place(x=200, y=400)
    username = is_login['username']
    out_botton = tkinter.Button(shop, text='退出购物', command=lambda: out_shop_chr(shop)).place(x=100, y=450)
    add_botton = tkinter.Button(shop, text='添加商品', command=lambda: add_shop_chr(id.get(), numb.get(), username)).place(
        x=200, y=450)

    shop.mainloop()

def pay():
    user_dict = business.open_file_read(os.path.join(os.path.abspath('db'), '%s.json' % is_login.get('username')))
    yue = user_dict['balance']
    need_money = 0
    # 计算需要的金额
    for i in user_dict['shop_car'].values():
        need_money += i[0] * i[1]
    # 如果总计大于余额提示用户额不足,否则结算成功,购物车清空
    if need_money > yue:
        tkinter.messagebox.showinfo(title='Hi', message='余额不足')
    else:
        user_dict['shop_car'] = {}
        user_dict['balance'] = yue - need_money
        business.open_file_write(os.path.join(os.path.abspath('db'), '%s.json' % is_login.get('username')), user_dict)
        tkinter.messagebox.showinfo(title='Hi', message=f'本次消费{need_money},余额:{yue - need_money}')
        name = is_login['username']
        logger1 = common.get_logger(f'{name}消费了{need_money}元')
        logger1.debug('结账业务')

def select_yve():
    user_dict = business.open_file_read(os.path.join(os.path.abspath('db'), '%s.json' % is_login.get('username')))
    yue = user_dict['balance']
    tkinter.messagebox.showinfo(title='Hi', message=f'余额:{yue}')

def to_money(*args):
    def pay(*args):
        business.to_money(*args)

    to_money = tkinter.Toplevel()
    sw = to_money.winfo_screenwidth()
    sh = to_money.winfo_screenheight()
    to_money.geometry("%dx%d+%d+%d" % (500, 350, (sw - 500) / 2, (sh - 350) / 2))
    to_money.title = '转账'
    to_name = tkinter.StringVar()
    to_name_label = tkinter.Label(to_money, text='转入的账号:').place(x=100, y=100)
    to_name_Entry = tkinter.Entry(to_money, textvariable=to_name).place(x=200, y=100)
    money = tkinter.StringVar()
    money_label = tkinter.Label(to_money, text='金额:').place(x=100, y=150)
    money_Entry = tkinter.Entry(to_money, textvariable=money).place(x=200, y=150)
    sure_button = tkinter.Button(to_money, text='确认转账',
                                 command=lambda: pay(is_login['username'], to_name.get(), money.get())).place(x=150,
                                                                                                              y=200)
    sure_button = tkinter.Button(to_money, text='退出', command=lambda: to_money.destroy()).place(x=250, y=200)
    to_money.mainloop()

def select_flowing_water():
    log_path = os.path.join(os.path.abspath('log'), 'a.log')
    log_list = []
    with open(log_path, 'r', encoding='utf8') as f:
        for i in f.readlines():
            if is_login['username'] in i:
                log_list.append(i)
        print(log_list)
    water = tkinter.Toplevel()
    sw = water.winfo_screenwidth()
    sh = water.winfo_screenheight()
    water.geometry("%dx%d+%d+%d" % (500, 350, (sw - 500) / 2, (sh - 350) / 2))
    water_listbox = tkinter.Listbox(water, selectmode=MULTIPLE, width=400, height=300)
    for i in log_list:
        water_listbox.insert(END, i)

    water_listbox.pack()
    water_listbox.mainloop()
    # tkinter.messagebox.showinfo(title='Hi', message=f'{log_list}')

def create_login(*args):
    is_login['username'] = args[0]
    print(is_login)
    win_login = tkinter.Tk()
    sw = win_login.winfo_screenwidth()
    sh = win_login.winfo_screenheight()
    win_login.geometry("%dx%d+%d+%d" % (500, 350, (sw - 500) / 2, (sh - 350) / 2))
    win_login.title('选择功能')
    lable_top = tkinter.Label(win_login,
                              text='欢迎光临,世纪联华超市!',  # 标签的文字
                              bg='pink',  # 背景颜色
                              font=('Arial', 12),  # 字体和字体大小
                              width=60, height=2)  # 标签长宽
    lable_top.pack(side='top')
    add_shop_chr = tkinter.Button(win_login, text='购物', width=20, command=add_shop).place(x=150, y=50)
    pay_shop_chr = tkinter.Button(win_login, text='结算', width=20, command=pay).place(x=150, y=100)
    move_money_to = tkinter.Button(win_login, text='转账', width=20, command=to_money).place(x=150, y=150)
    select_info = tkinter.Button(win_login, text='查看流水', width=20, command=select_flowing_water).place(x=150, y=200)
    select_balance = tkinter.Button(win_login, text='查看余额', width=20, command=select_yve).place(x=150, y=250)
    sign_out = tkinter.Button(win_login, text='退出登入', width=20, command=lambda: out_login(win_login, args[1])).place(
        x=150, y=300)
    win_login.mainloop()

Windows.py

import tkinter
from tkinter import *
from tkinter import messagebox
from core import business
from core import win_login
import hashlib
import os
from start import db_path
import json
def run():
    pass

def click_login_botton():
    a = business.login(name.get(), pwd.get())
    if a == 0:
        print(tkinter.messagebox.showinfo(title='Hi', message='登入成功'))
        win_login.create_login(name.get(), win)
    elif a == 1:
        print(tkinter.messagebox.showinfo(title='Hi', message='用户不存在'))
        return
    elif a == 2:
        print(tkinter.messagebox.showinfo(title='Hi', message='账号或密码错误'))
        return

def click_register_button():
    def register():
        print(new_name.get(), new_pwd.get(), new_pwd_two.get())
        a = business.register(new_name.get(), new_pwd.get(), new_pwd_two.get())
        if a == 0:
            tkinter.messagebox.showinfo(title='Hi', message='注册成功')
            win_register.destroy()
        elif a == 1:
            print(tkinter.messagebox.showinfo(title='Hi', message='密码不一致'))
            win_register.destroy()
        else:
            print(tkinter.messagebox.showinfo(title='Hi', message='账号已存在'))
            win_register.destroy()

    win_register = tkinter.Toplevel(win)
    sw = win_register.winfo_screenwidth()
    sh = win_register.winfo_screenheight()
    win_register.geometry("%dx%d+%d+%d" % (300, 170, (sw - 300) / 2, (sh - 170) / 2))
    win_register.title('注册')
    # win_register.geometry('300x170')
    name_Label = tkinter.Label(win_register, text='用户名 ').place(x=20, y=20)
    pwd_Label = tkinter.Label(win_register, text='密码 ').place(x=20, y=60)
    pwd_two_Label = tkinter.Label(win_register, text='再次确认密码 ').place(x=20, y=100)
    new_name = tkinter.StringVar()
    new_pwd = tkinter.StringVar()
    new_pwd_two = tkinter.StringVar()
    name_Entry = tkinter.Entry(win_register, textvariable=new_name).place(x=100, y=20)
    pwd_Entry = tkinter.Entry(win_register, show='*', textvariable=new_pwd).place(x=100, y=60)
    pwd_two_Entry = tkinter.Entry(win_register, show='*', textvariable=new_pwd_two).place(x=100, y=100)
    register_button = tkinter.Button(win_register, text='注册', command=register).place(x=150, y=130)
    win_register.mainloop()

win = tkinter.Tk()
win.title('购物车+ATM')
# win.geometry('450x200')
sw = win.winfo_screenwidth()
# 得到屏幕宽度
sh = win.winfo_screenheight()
# 得到屏幕高度
ww = 450
wh = 200
# 窗口宽高为100
x = (sw - ww) / 6
y = (sh - wh) / 2
win.geometry("%dx%d+%d+%d" % (ww, wh, x, y))

lable_top = tkinter.Label(win,
                          text='欢迎光临,世纪联华超市!',  # 标签的文字
                          bg='pink',  # 背景颜色
                          font=('Arial', 12),  # 字体和字体大小
                          width=60, height=2)  # 标签长宽
lable_top.pack(side='top')
username_lable = tkinter.Label(win, text='用户名 ').place(x=120, y=90)
password_lable = tkinter.Label(win, text='密码 ').place(x=120, y=120)
name = tkinter.StringVar()
pwd = tkinter.StringVar()
username_entry = tkinter.Entry(win, textvariable=name).place(x=180, y=90)
password_entry = tkinter.Entry(win, show='*', textvariable=pwd).place(x=180, y=120)
login_button = tkinter.Button(win, text='登入', command=click_login_botton).place(x=180, y=160)
register_button = tkinter.Button(win, text='注册', command=click_register_button).place(x=270, y=160)
win.mainloop()

common.py

import logging
from conf import settings
from logging import config

def get_logger(msg):
    # 记录日志
    logging.config.dictConfig(settings.LOGGING_DIC)  # 自动加载字典中的配置
    logger1 = logging.getLogger(msg)
    return logger1  # 返回一个logger1对象

start.py

import os
import sys
from core import Windows

sys.path.append(os.path.dirname(__file__))
db_path = os.path.join(os.path.dirname(__file__), 'db')
if not os.path.exists(db_path):
    os.makedirs(db_path)

if __name__ == '__main__':
    Windows.run()

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章