#!/usr/bin/env python3
# _*_ coding:utf-8 _*_
#
# Author: Payne Zheng <zzuai520@live.com>
# Date: 2018-04-12 16:41:15
# Location: DongGuang
# Desc: shopping car
#
"""
1、启动程序后,输入用户名密码后,让用户输入工资,然后打印商品列表
2、允许用户根据商品编号购买商品
3、用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒
4、可随时退出,退出时,打印已购买商品和余额
5、在用户使用过程中, 关键输出,如余额,商品已加入购物车等消息,需高亮显示
扩展需求:
1、用户下一次登录后,输入用户名密码,直接回到上次的状态,即上次消费的余额什么的还是那些,再次登录可继续购买
2、允许查询之前的消费记录
3、余额不足时充许充值
4、余额不足时充许修改购物车里的商品
"""
import os
import json
import time
# 商品列表
products = [
{"name": "电脑", "price": 1999},
{"name": "鼠标", "price": 10},
{"name": "游艇", "price": 20},
{"name": "美女", "price": 998},
]
# 常量
SHOP_LOG_FILE = "shop_log.txt"
SHOP_CAR_FILE = "shop_car.json"
BALANCE_FILE = "balance.json"
# 变量
user_name = "jack"
pay_pass = "123456"
login_pass = "abc123"
shop_price = 0
balance = 0
shop_car = []
flag = True
class Colored(object):
"""打印高亮颜色字体"""
# 显示格式: \033[显示方式(1:高亮/0:正常);前景色;背景色m
# 只写一个字段表示前景色,背景色默认,以下全为高亮显示
HIGHLIGHT_RED = '\033[1;31m' # 红色
HIGHLIGHT_GREEN = '\033[1;32m' # 绿色
HIGHLIGHT_YELLOW = '\033[1;33m' # 黄色
HIGHLIGHT_BLUE = '\033[1;34m' # 蓝色
#: color reset
RESET = '\033[0m' # 终端默认颜色
def color_str(self, colors, s):
return '{}{}{}'.format(
getattr(self, colors),
s,
self.RESET
)
def red(self, s):
return self.color_str('HIGHLIGHT_RED', s)
def green(self, s):
return self.color_str('HIGHLIGHT_GREEN', s)
def yellow(self, s):
return self.color_str('HIGHLIGHT_YELLOW', s)
def blue(self, s):
return self.color_str('HIGHLIGHT_BLUE', s)
def Login():
"""帐号登录"""
input_user = input(color.blue("请输入你的帐号:"))
if input_user == user_name and AuthPasswod('登录', login_pass):
print(color.green("\n登录成功,欢迎<%s>\n" % input_user))
else:
exit(color.red("帐号错误,请重新登录"))
def RechargeBalance():
"""充值"""
global balance
re_balance = input(color.blue("\n请输入你的充值金额(小写数字): "))
if re_balance.isdigit():
re_balance = int(re_balance)
balance += re_balance
return balance
else:
print(color.red('您输入的金额格式不对,充值失败!'))
def GetProductList(plist, title="购物车"):
"""格式化打印商品列表"""
print(color.blue(title.center(30, '='))
for i, n in enumerate(plist):
print(color.yellow("%s. %s %s" % (i, n['name'], n['price'])))
def GetTotalPrice(_price):
"""计算选购商品总价"""
for i, n in enumerate(shop_car):
_price += n['price']
return int(_price)
def CheckBalance(_balance, total_shop_price):
"""检查余额"""
tag = True if _balance >= total_shop_price else False
return tag
def AuthPasswod(tag, auth_pass):
"""验证密码"""
count = 0
while count < 3:
input_pass = input(color.blue("请输入您的%s密码:" % tag))
count += 1
if input_pass == auth_pass:
return True
else:
print(color.red("%s密码错误,请重试:" % tag))
else:
return False
def DataDump(file, data):
"""
序列化存储已加入购物车商品列表与价格与消费记录
file: 购物车、价格、消费记录存入不同文件
data: 要在序列化的数据
"""
with open(file, 'w', encoding='utf-8') as f:
json.dump(data, f)
def DataLoad(file):
"""读取已加入购物车商品与价格"""
with open(file, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
def WriteShopLog(_shop_car, _balance):
"""记录购买消费记录"""
log_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
with open(SHOP_LOG_FILE, 'a', encoding='utf-8') as f:
f.writelines("%s : \n您购买了如下商品:\n" % log_time)
for i, n in enumerate(_shop_car):
f.writelines('%s. %s %s\n' % (i, n['name'], n['price']))
f.writelines('消费金额:%s\n--------------------\n\n' % _balance)
def ReadShopLog():
"""读取购买消费记录"""
try:
with open(SHOP_LOG_FILE, 'r', encoding='utf-8') as f:
print(color.yellow("您的消费记录如下:\n%s" % (f.read())))
go_back = input(color.green('\n【返回商品列表:b】:')).strip()
if go_back == 'b':
pass
except FileNotFoundError:
print(color.red('您还没有消费记录'))
def ChangShopCar(_shop_car):
while True:
GetProductList(_shop_car)
num = input(color.blue('【请选择要从购物车删除的商品编号:(0-%s) ; 返回:b】:' % (len(_shop_car)-1))).strip()
if num.isdigit() and int(num) < len(_shop_car):
num = int(num)
print(color.yellow('已将商品<%s>从购物车删除!' % _shop_car[num]['name']))
del _shop_car[num]
elif num == "b":
break
else:
print(color.red('您购物车中没有所选商品,请重试!'))
# 购物车为空返回选购列
if len(_shop_car) < 1:
print(color.red('\n购物车为空!!!\n'))
break
def CheckOut(_shop_car, _shop_price):
global flag, balance
GetProductList(_shop_car)
total_shop_price = GetTotalPrice(_shop_price)
print(color.yellow("商品总价:%s" % total_shop_price))
print('\n您帐号余额为:%s' % balance)
## 检查余额
if CheckBalance(balance, total_shop_price):
# 支付
pay = input(color.blue('\n【按任意键返回商品列表;支付请按:p】:')).strip()
if pay == 'p':
if AuthPasswod('支付', pay_pass):
balance -= total_shop_price
WriteShopLog(_shop_car, total_shop_price)
_shop_car.clear()
print(color.green("\n支付成功, 您的余额为:%s" % balance))
go_on = input(color.blue("\n【按任意键继续选购; 退出:q】>>")).strip()
if go_on == 'q':
flag = False
else:
print(color.red('\n重试次数过多!支付失败!'))
## 余额不足=>提供充值与删除购物车商品选项
else:
rod = input(color.red("\n【对不起你的余额不足! 充值:r ; 删除已选商品:d】")).strip()
# 充值
if rod == 'r':
RechargeBalance()
print(color.green('\n充值成功,余额:%s' % balance))
# 修改购物车商品
elif rod == 'd':
ChangShopCar(_shop_car)
def GetExitStatus():
"""获取上次退出时购物车与余额状态"""
global flag, shop_car
if os.path.isfile(SHOP_CAR_FILE):
shop_car = DataLoad(SHOP_CAR_FILE)
GetProductList(shop_car)
print(color.yellow('商品总价>>: %s' % (GetTotalPrice(shop_price))))
print(color.yellow('\n帐户余额:%s' % balance))
yes = input(color.blue('\n【按任意键继续,按q退出】:')).strip()
if yes == 'q':
flag = False
def GetBalance():
"""获取帐户余额"""
global balance
# 读不到余额文件就表示第一次登录,让用户存入金额
balance = DataLoad(BALANCE_FILE) if os.path.isfile(BALANCE_FILE) else RechargeBalance()
def GoShopping():
""""购物"""
global flag, balance
### 打印商品列表
GetProductList(products, "商品列表")
choice = input("\n【请选择你购买的商品编号:(0-%s); 查看消费记录:h ; 查看余额:l ; 查看购物车:s ; 退出:q】:"
% (len(products)-1)).strip()
### 判断输入为数字则选择商品并加入购物车
if choice.isdigit():
choice = int(choice)
if choice < len(products):
shop_car.append(products[choice])
print(color.yellow("\n已添加商品<%s>到购物车\n" % products[choice]['name']))
else:
print(color.red("\n您输入的商品编号不存在,请重新输入:"))
### 查看余额
elif choice == "l":
print(color.green('\n您的余额为:%s\n' % balance))
### 结算
elif choice == "s":
print(balance)
CheckOut(shop_car, shop_price)
### 查看消费记录
elif choice == 'h':
ReadShopLog()
### 退出
elif choice == 'q':
flag = False
### 其它无效选项
else:
print(color.red('\n没有这个选项,请重新选择\n'))
def main():
"""程序主入口"""
global balance
Login()
GetBalance()
GetExitStatus()
while flag:
GoShopping()
else:
DataDump('shop_car.json', shop_car)
DataDump('balance.json', balance)
exit(color.yellow("\n欢迎下次光临"))
if __name__ == "__main__":
color = Colored()
main()