購物車+ATM專案(圖形化)
阿新 • • 發佈:2022-04-03
專案目錄結構
執行效果
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()