洗礼灵魂,修炼python(82)--全栈项目实战篇(10)—— 信用卡+商城项目(模拟京东淘宝)...

news/2024/10/15 22:30:23/

本次项目相当于对python基础做总结,常用语法,数组类型,函数,文本操作等等

本项目在博客园里其他开发者也做过,我是稍作修改来的,大体没变的

 

项目需求:

信用卡+商城:


A、信用卡(类似白条/花呗)

1.额度15000以上或者自定义
2.可以提现,手续费5%
3.账户信息,信用卡和购物车共用
4.支持账户间转账
5.支持购物结账功能
6.有还款功能
7.记录每月日常消费流水
8.每个重要步骤都要记录到日志文件里(用logging模块)
9.有管理员功能,添加账户,冻结账户,调整用户额度
(可选)10.每月19号出帐,27号为最后还款日,逾期未还,按利息为欠款总额的万分之5每日计算

B、在线购物商场

1.与信用卡信息对接,支持信用卡结账
2.登录验证用装饰器
3.支持多账户登录
4.有多个页面,个人主页,电脑,手机,日用品主页,具体多少个主页随意(结合前面学到的)
5.每进入一个页面,分别打印页面下的产品
6.个人页面,电脑,手机等页面可以退回到主页 (类似前面的多级菜单同样的功能)

分析:

本次项目由于项目比前面的难度有提升,并且涉及到贴合以后真正的开发,很多设置都是可修改,并不是前面的项目那样,单个文件就搞定的。要求不用多说,就和常识里使用到的类似京东的白条,支付宝的蚂蚁花呗,然后加上一个购物商场,功能也不用多说。但是文件很多,由此,画一个流程图解释:

 

这个流程图我使用的百度脑图画的,分享链接:http://naotu.baidu.com/file/8ecc09fd00d5016349e4e7f72583ec48

画得比较简单,每个文件都有备注是干嘛的。

 

其实这个没什么难度,流程还是那些,登录验证,交易,更新数据,结束

流程图:

剩下的就是每个文件的编写,以及如何让这些文件联系起来了

 

这里说个知识点:

# 将当前py文件的上级文件夹目录的路径添加到模块索引列表内import sys,os
path  = os.path.dirname(__file__)sys.path.append(path)

 

以上的代码则可以把你的文件作为py文件导入并且不怕因为文件路径被修改而导致导入失败了

 

 

代码:

项目包下载链接:传送门

需要的文件:

 

 

card.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/19 0019 21:41import os,sysbase_dir = os.path.dirname(os.path.dirname(__file__))sys.path.append(base_dir)from libs import mainif __name__ == '__main__':main.run()

 

main.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/19 0019 21:43import os,sysbase_dir = os.path.dirname(os.path.dirname(__file__))
sys.path.append(base_dir)from libs import auth
from libs import logger
from libs import transaction
from libs import accounts
from conf import settings# 用户数据,作为标志位以及缓存用户信用卡信息
account_data = {'account_id':None,'is_auth':False,'data':None
}# 用户日志
account_log = logger.logger('account')# 交易日志
transaction_log = logger.logger('transaction')# 账户信息
def userinfo(data):'''print user of data:param data: user data:return:'''for k,v in data.items():print(k,':',v)# 查询账单
def select(data):'''check transaction data:param data: user data:return:'''check_path = '%s/log/transaction.log'%settings.BASE_DIRwith open(check_path) as f:for i in f.readlines():if str(data['id']) in i:print(i)# 退出
def logout(data):'''quit the programs func:param data: user data:return:'''print('account [%s] quit...'%data['id'])exit()# 还款
def repay(data):'''user repay bill:param data: user data:return:'''corrent_accdata = accounts.corrent_accdata(data['id'])print('''---------- user %s bill ----------creadit:    %sbalance:    %s'''%(corrent_accdata['id'],corrent_accdata['credit'],corrent_accdata['balance']))back_flag = Falsewhile  not back_flag:repay_amount = input("\033[36;1mplease enter amount or 'b' to back:\033[0m").strip()if repay_amount == 'b':back_flag = Trueprint() #此处的打印空是为了换行美观,否则日志输出会和repay_amount在同一行if len(repay_amount) > 0 and repay_amount.isdigit():new_data = transaction.change(corrent_accdata,repay_amount,transaction_log,'repay')if new_data:print('\033[46;1mnew balance:[%s]\033[0m'%new_data['balance'])else:print('\033[31;1m[%s] not integer,only support integer\033[0m'%repay_amount)if repay_amount == 'b':back_flag = True# 取款
def draw(data):'''user repay bill:param data: user data:return:'''corrent_accdata = accounts.corrent_accdata(data['id'])print('''---------- user %s bill ----------creadit:    %sbalance:    %s'''%(corrent_accdata['id'],corrent_accdata['credit'],corrent_accdata['balance']))back_flag = Falsewhile  not back_flag:draw_amount = input("\033[36;1mplease enter amount or 'b' to back:\033[0m").strip()if draw_amount == 'b':back_flag = Trueif len(draw_amount) > 0 and draw_amount.isdigit():new_data = transaction.change(corrent_accdata,draw_amount,transaction_log,'draw')if new_data:print('\033[46;1mnew balance:[%s]\033[0m'%new_data['balance'])else:print('\033[31;1m[%s] not integer,only support integer\033[0m'%draw_amount)# 转账
def transfer(data):'''user1 transfer money to user2:param data: user data:return:'''corrent_accdata = accounts.corrent_accdata(data['id'])print('''---------- user %s bill ----------creadit:    %sbalance:    %s'''%(corrent_accdata['id'],corrent_accdata['credit'],corrent_accdata['balance']))back_flag = Falsewhile  not back_flag:transfer_amount = input("\033[36;1mplease enter amount or 'b' to back:\033[0m").strip()if transfer_amount == 'b':back_flag = Trueif len(transfer_amount) > 0 and transfer_amount.isdigit():transfer_user_id = input("\033[36;1mplease enter user id :\033[0m").strip()try:transfer_userdata = accounts.corrent_accdata(transfer_user_id)new_data = transaction.change(corrent_accdata,transfer_amount,transaction_log,'transfer')if new_data:transfer_userdata['balance'] += float(transfer_amount)accounts.dump_accdata(transfer_userdata)print('\033[46;1mtrade successfully!\033[0m')print('\033[46;1mnew balance:[%s]\033[0m'%new_data['balance'])except Exception as reason:print('\033[31;1mtransaction failure!\033[0m')print(reason)else:print('\033[31;1m[%s] not integer,only support integer\033[0m'%transfer_amount)# 信用卡操作对象
def optionlist(data):''':param data: user's data:return:'''menu = u'''\033[32;1m1.账户信息2.还款3.取款4.转账5.查询账单6.退出\033[0m'''option_dict = {'1':userinfo,'2':repay,'3':draw,'4':transfer,'5':select,'6':logout}exit_flag = Falsewhile  not exit_flag:print(menu)user_option  = input('\033[36;1mplease enter the option number:\033[32;1m')if user_option in option_dict:option_dict[user_option](data)else:print("\033[31;1m sorry,haven't option [%s]\033[0m"%user_option)# 运行
def run():'''运行函数,将整个项目运行起来:return:'''userdata = auth.login(account_data,account_log)if account_data['is_auth'] == True:account_data['data'] = userdataoptionlist(userdata)

 

 

logger.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/19 0019 21:54import logging
from conf import settingsdef logger(log_type):# 创建一个文件型日志对象log_file = '%s/log/%s'%(settings.BASE_DIR,settings.LOG_TYPE[log_type])fh = logging.FileHandler(log_file)fh.setLevel(settings.LOG_LEVEL)# 创建一个输出到屏幕型日志对象sh = logging.StreamHandler()sh.setLevel(settings.LOG_LEVEL)# 设置日志格式formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 添加格式到文件型和输出型日志对象中fh.setFormatter(formater)sh.setFormatter(formater)# 创建log对象,命名logger = logging.getLogger(log_type)logger.setLevel(settings.LOG_LEVEL)# 把文件型日志和输出型日志对象添加进loggerlogger.addHandler(fh)logger.addHandler(sh)return logger

 

auth.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/19 0019 21:53import json,os,time
from conf import settings
from libs import dbdef auth(userid,password):'''account libs func:param userid: user card id:param password: user pasword:return:'''userdbpath = db.db(settings.DATABASEINFO)account_file = '%s/%s.json'%(userdbpath,userid)# print(account_file)if os.path.isfile(account_file):with open(account_file) as f:account_data = json.load(f)if account_data['password'] == password:indate = time.mktime(time.strptime(account_data['expire_date'],'%Y-%m-%d'))if indate < time.time():print("\033[31;1m your card was out of date\033[0m")else:return account_dataelse:print('\033[31;1m your id or password incorrect\033[0m')else:print('\033[31;1maccount [%s] does not exist\033[0m'%userid)def login(data,logobj):'''account login func:param data: user's data:param logobj: account logger object:return:'''count = 0while data['is_auth'] is not True and count < 3:userid = input("\033[36;1mplease enter your card's id:\033[0m").strip()password = input('\033[36;1menter your password:\033[0m').strip()userauth = auth(userid,password)if userauth:data['is_auth'] = Truedata['account_id'] = useridreturn userauthcount +=1else:logobj.error('\033[31;1maccount [%s] too many login attempts\033[0m' % userid)exit()

 

accounts.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/20 0020 22:38from conf import settings
from libs import db
import jsondef corrent_accdata(userid):''':param userid: user  card's id:return:'''accdata_path = db.db(settings.DATABASEINFO)acc_file = '%s/%s.json'%(accdata_path,userid)with open(acc_file) as f:corrent_accdata = json.load(f)return corrent_accdatadef dump_accdata(data):''':param data: user data:return:'''accdata_path = db.db(settings.DATABASEINFO)acc_file = '%s/%s.json'%(accdata_path,data['id'])with open(acc_file,'w') as f:json.dump(data,f)return True

 

transaction.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/20 0020 17:50from conf import settings
from libs import accountsdef change(account_data,amount,logobj,trantype):''':param account_data: user data:param amount: user entered amount:param logobj: transaction logging object:param trantype: transaction type:return:'''amount = float(amount)if trantype in settings.TRAN_TYPE:interest = amount * settings.TRAN_TYPE[trantype]['interest'] #利息old_balance = account_data['balance']if settings.TRAN_TYPE[trantype]['action'] == 'plus':new_balance = old_balance + amount +interestelif settings.TRAN_TYPE[trantype]['action'] == 'minus':new_balance = old_balance - amount - interestif new_balance < 0:print("\033[31;1maccount [%s] balance is not sufficient to pay [%s]!\033[0m"%(account_data['id'],amount +interest))returnaccount_data['balance'] = new_balanceaccounts.dump_accdata(account_data)logobj.info('account:%s - transaction:%s - amount:%s - interest:%s'%(account_data['id'],trantype,amount,interest))return account_dataelse:print('\033[31;1mTransaction type [%s] is not exist!\033[0m'%trantype)

 

settings.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/19 0019 21:56import os,sys,logging# 项目根目录
BASE_DIR = os.path.dirname(os.path.dirname(__file__))# 设置日志等级
LOG_LEVEL = logging.INFO# 存储日志类型
LOG_TYPE = {'transaction':'transaction.log','account':'account.log'}# 数据库信息
DATABASEINFO = {'engine':'file',# 数据库类型,可以为文件,可以为数据库'dirname':'accounts',# 数据文件目录名'path':'%s/db'%BASE_DIR
}# 交易类型
TRAN_TYPE = {'repay':{'action':'plus','interest':0},'draw':{'action':'minus','interest':0.05},'transfer':{'action':'minus','interest':0.05}
}

 

db.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/19 0019 22:51def fl_db(parms):''':param parms: malldb type:return: malldb path'''# print('file malldb:,parms')db_path = '%s/%s'%(parms['path'],parms['dirname'])# print(db_path)return db_pathdef ml_db(parms):passdef mo_db(parms):passdef oe_db(parms):passdef db(parms):''':param parms: malldb information:return:'''db_dict = {'file':fl_db,'mysql':ml_db,'mongodb':mo_db,'orlcle':oe_db,}if parms['engine'] in db_dict:return db_dict[parms['engine']](parms)

 

example.py:

#!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/20 0020 15:43import json,sys,os,datetimebase_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
sys.path.append(base_dir)from conf import settings
from libs import dbpath = db.db(settings.DATABASEINFO)acc_dic = {'id': 123, #卡号'password': 'abc', #密码'credit': 15000, #额度'balance': 15000, #余额'enroll_date': '2016-01-02', #注册日期'expire_date': '2021-01-01', #失效日期'pay_day': 22, #还款日'status': 0 # 0 = normal, 1 = locked, 2 = disabled
}id = int(input('\033[36;1menter your user id:\033[0m'))
corrent_path = '%s/%s.json'%(path,id)acc_dic['id'] = idenroll_date = datetime.date.today()
expire_date = enroll_date + datetime.timedelta(days=365*5)acc_dic['enroll_date'] = str(enroll_date)
acc_dic['expire_date'] = str(expire_date)with open(corrent_path,'w') as f:json.dump(acc_dic,f)

 

 shopping.py:

 #!usr/bin/env python
#-*- coding:utf-8 -*-# author:yangva
# datetime:2018/1/21 0024 17:44import sys,json,os
from collections import Counterbase_dir = os.path.dirname(os.path.dirname(__file__))
sys.path.append(base_dir)from card.conf import settings
from card.libs import db# # 载入商城账号信息,商城和信用卡并不是等同的
# user_path = '%s/mall/yang.json'%base_dir
# with open(user_path) as f:
#     userdata = json.load(f)# # 读取信用卡
# path = db.db(settings.DATABASEINFO)
# account_path = '%s/%s.json'%(path,userdata['id'])
# with open(account_path) as f:
#     accountdata = json.load(f)# # 账户可用余额
# salary = accountdata['balance']
# #缓存总额,用于后面总共消费多少作计算
# temp = salary#购物车
cart = []#商品总清单
product ={'手机':{'1':{'IphoneX':8388.00},'2':{'Iphone8':5088.00},'3':{'一加5T':3270.00},'4':{'魅族pro7':1999.00},'5':{'小米MIX2':3299.00},'6':{'华为p10':3488.00}},'电脑':{'7':{'联想R720-15I':7399.00},'8':{'惠普战66ProG1':6499.00},'9':{'戴尔XPS13':6299.00},'10':{'MacBookAir':6988.00}},'日用品':{'11':{'高露洁牙刷':12.90},'12':{'三利纯棉浴巾':32.50},'13':{'半球电水壶':49.00}}
}login_status = False  #登录状态标志位#登录验证
def login(func):def inner():global login_status,accountdata,salary,temp,account_pathwhile not login_status:print('\033[32;1m请登录\033[0m')username = input('\033[32;1musername:\033[0m')password = input('\033[32;1mpassword:\033[0m')user_path = '%s/mall/%s.json'%(base_dir,username)if os.path.isfile(user_path):with open(user_path) as f:userdata = json.load(f)while password != userdata[username]: # 购物商场可以无限次登录print('\033[31;1m用户名或密码错误,请重新登录\033[0m')password = input('\033[32;1mpassword:\033[0m')else:print('\033[34;1m登录成功!\n')login_status = Truepath = db.db(settings.DATABASEINFO)# 载入信用卡信息account_path = '%s/%s.json'%(path,userdata['id'])with open(account_path) as f:accountdata = json.load(f)# 账户可用余额salary = accountdata['balance']#缓存总额,用于后面总共消费多少作计算temp = salaryreturn func()else:print('\033[31;1m不存在的用户名或者用户文件\033[0m')else: #已登录状态return func()return inner#手机页面
@login
def phone(string='手机'):shopping_cart(string)#电脑页面
@login
def pc(string='电脑'):shopping_cart(string)#日用品页面
@login
def life(string='日用品'):shopping_cart(string)#主页
@login
def home():print('\033[36;1m首页,js动态切换图片;精品促销;XX品牌日\033[0m')#消费流水
@login
def consume():consume = temp-salary #消费金额if consume > 0:print('\033[36;1m您当前的消费流水详细账单:\033[0m')for i,j in dict(Counter(cart)).items():print('\033[36;1m%s 数量:%s\033[0m'%(i,j))print('\033[46;1m您总共消费了 %.2f 元,可用余额为 %.2f 元\033[0m\n'%(temp-salary,salary))else:print('\033[31;1m您还未购买任何物品\033[0m\n')# 更新用户数据
def dump():accountdata['balance'] = salarywith open(account_path,'w') as f:json.dump(accountdata,f)return accountdata# 退出
def logout():acc = dump()if acc:print('\033[36;1m欢迎下次光临!您已退出!\033[0m')exit()#购物车
def shopping_cart(string):global salaryfor page,goods_msg in product.items():if page == string:while True:print('\033[36;1m页面:%s\033[0m\n'%page)for ID,goods in goods_msg.items():for name,price in goods.items():print('\033[32;1m商品id:%s\t\t\t商品名:%s\t\t\t价格:%s\033[0m'%(ID,name,price))shopping = input('\033[32;1m请输入商品id(需要返回上一级菜单请输入“b”)>>>:\033[0m')if shopping in goods_msg.keys():gname = list(goods_msg[shopping].keys())[0]gprice =list(goods_msg[shopping].values())[0]if salary < gprice:print('\033[31;1m您的余额不足\033[0m')else:salary -= gpriceprint('\033[46;1m您已购买商品 %s -- 单价 %.2f,剩余余额:%.2f\033[0m\n'%(gname,gprice,salary))cart.append('商品:%s 单价:%.2f'%(gname,gprice))if not salary: #购买后再次检测信用卡剩余额度print('\033[31;1m您的余额为0,不能再购买任何东西,程序已退出,欢迎下次光临\033[0m')breakelif shopping == 'b': #购买结束,到收银台结账print('\033[32;1m已返回上一级\033[0m\n')breakelse:print('\033[31;1m您的输入有误,请查看是否有id为【%s】的商品\033[0m'%shopping)#主函数
def man():mapper = {'1':home,'2':pc,'3':phone,'4':life,'5':consume,'6':logout} #映射函数print('\033[32;1m-------欢迎光临XXX商城-------\033[0m')while True:print('\033[32;1m1.主页\n2.电脑\n3.手机\n4.日用品\n5.打印流水凭条\n6.退出\033[0m')page = input('\033[32;1m请选择访问页面(输入前面的序号即可):\033[0m')if page in mapper:mapper[page]()else:print('\033[31;1m输入有误!!\033[0m')if __name__ == '__main__':man()

 

62285580.json:

{"status": 0, "password": "123", "expire_date": "2020-07-26", "balance": 1500.75, "pay_day": 22, "id": 62285580, "enroll_date": "2015-07-25", "credit": 15000}

 

62285589.json:

{"status": 0, "password": "abc", "expire_date": "2021-01-01", "balance": 16022.05, "pay_day": 22, "id": 62285589, "enroll_date": "2016-01-02", "credit": 15000}

 

以下两个文件是购物商场的账户数据文件,你也可以统一的放在一个json里

yang.json:

{"yang": "abc", "id": 62285589}

 

ling.json:

{"ling": "123", "id": 62285580}

 

 

 运行效果:

运行card.py:

 

(部分截图)

详细结果:

please enter your card's id:62285589
enter your password:abc1.账户信息2.还款3.取款4.转账5.查询账单6.退出
please enter the option number:2
---------- user 62285589 bill ----------creadit:    15000balance:    16022.05please enter amount or 'b' to back:500new balance:[16522.05]
please enter amount or 'b' to back:2018-01-24 17:03:06,773 - transaction - INFO - account:62285589 - transaction:repay - amount:500.0 - interest:0.0
b[b] not integer,only support integer1.账户信息2.还款3.取款4.转账5.查询账单6.退出
please enter the option number:1
status : 0
password : abc
expire_date : 2021-01-01
balance : 16022.05
pay_day : 22
id : 62285589
enroll_date : 2016-01-02
credit : 150001.账户信息2.还款3.取款4.转账5.查询账单6.退出
please enter the option number:3
---------- user 62285589 bill ----------creadit:    15000balance:    16522.05please enter amount or 'b' to back:100
2018-01-24 17:04:52,005 - transaction - INFO - account:62285589 - transaction:draw - amount:100.0 - interest:5.0
new balance:[16417.05]
please enter amount or 'b' to back:b
[b] not integer,only support integer1.账户信息2.还款3.取款4.转账5.查询账单6.退出
please enter the option number:4
---------- user 62285589 bill ----------creadit:    15000balance:    16417.05please enter amount or 'b' to back:200
please enter user id :62285580
2018-01-24 17:05:11,616 - transaction - INFO - account:62285589 - transaction:transfer - amount:200.0 - interest:10.0
trade successfully!
new balance:[16207.05]
please enter amount or 'b' to back:b
[b] not integer,only support integer1.账户信息2.还款3.取款4.转账5.查询账单6.退出
please enter the option number:5
2018-01-21 20:21:53,140 - transaction - INFO - account:62285589--transaction:repay--amount:400.0--interest:0.02018-01-21 20:25:43,037 - transaction - INFO - account:62285589--transaction:draw--amount:400.0--interest:20.02018-01-21 20:27:08,946 - transaction - INFO - account:62285589--transaction:draw--amount:400.0--interest:20.02018-01-21 20:31:55,979 - transaction - INFO - account:62285589 - transaction:transfer - amount:100.0 - interest:5.02018-01-24 17:03:06,773 - transaction - INFO - account:62285589 - transaction:repay - amount:500.0 - interest:0.02018-01-24 17:04:52,005 - transaction - INFO - account:62285589 - transaction:draw - amount:100.0 - interest:5.02018-01-24 17:05:11,616 - transaction - INFO - account:62285589 - transaction:transfer - amount:200.0 - interest:10.01.账户信息2.还款3.取款4.转账5.查询账单6.退出
please enter the option number:6
account [62285589] quit...

 

运行shopping.py:

 

 

详细结果:

-------欢迎光临XXX商城-------
1.主页
2.电脑
3.手机
4.日用品
5.打印流水凭条
6.退出
请选择访问页面(输入前面的序号即可):2
请登录
username:yang
password:abc
登录成功!页面:电脑商品id:7			商品名:联想R720-15I			价格:7399.0
商品id:8			商品名:惠普战66ProG1			价格:6499.0
商品id:9			商品名:戴尔XPS13			价格:6299.0
商品id:10			商品名:MacBookAir			价格:6988.0
请输入商品id(需要返回上一级菜单请输入“b”)>>>:b
已返回上一级1.主页
2.电脑
3.手机
4.日用品
5.打印流水凭条
6.退出
请选择访问页面(输入前面的序号即可):1
首页,js动态切换图片;精品促销;XX品牌日
1.主页
2.电脑
3.手机
4.日用品
5.打印流水凭条
6.退出
请选择访问页面(输入前面的序号即可):3
页面:手机商品id:1			商品名:IphoneX			价格:8388.0
商品id:2			商品名:Iphone8			价格:5088.0
商品id:3			商品名:一加5T			价格:3270.0
商品id:4			商品名:魅族pro7			价格:1999.0
商品id:5			商品名:小米MIX2			价格:3299.0
商品id:6			商品名:华为p10			价格:3488.0
请输入商品id(需要返回上一级菜单请输入“b”)>>>:4
您已购买商品 魅族pro7 -- 单价 1999.00,剩余余额:14208.05页面:手机商品id:1			商品名:IphoneX			价格:8388.0
商品id:2			商品名:Iphone8			价格:5088.0
商品id:3			商品名:一加5T			价格:3270.0
商品id:4			商品名:魅族pro7			价格:1999.0
商品id:5			商品名:小米MIX2			价格:3299.0
商品id:6			商品名:华为p10			价格:3488.0
请输入商品id(需要返回上一级菜单请输入“b”)>>>:b
已返回上一级1.主页
2.电脑
3.手机
4.日用品
5.打印流水凭条
6.退出
请选择访问页面(输入前面的序号即可):4
页面:日用品商品id:11			商品名:高露洁牙刷			价格:12.9
商品id:12			商品名:三利纯棉浴巾			价格:32.5
商品id:13			商品名:半球电水壶			价格:49.0
请输入商品id(需要返回上一级菜单请输入“b”)>>>:11
您已购买商品 高露洁牙刷 -- 单价 12.90,剩余余额:14195.15页面:日用品商品id:11			商品名:高露洁牙刷			价格:12.9
商品id:12			商品名:三利纯棉浴巾			价格:32.5
商品id:13			商品名:半球电水壶			价格:49.0
请输入商品id(需要返回上一级菜单请输入“b”)>>>:b
已返回上一级1.主页
2.电脑
3.手机
4.日用品
5.打印流水凭条
6.退出
请选择访问页面(输入前面的序号即可):5
您当前的消费流水详细账单:
商品:魅族pro7 单价:1999.00 数量:1
商品:高露洁牙刷 单价:12.90 数量:1
您总共消费了 2011.90 元,可用余额为 14195.15 元1.主页
2.电脑
3.手机
4.日用品
5.打印流水凭条
6.退出
请选择访问页面(输入前面的序号即可):6
欢迎下次光临!您已退出!

 

打开json文件验证:

 

表示同步成功

 

总结:

其实还有两个问题:

1.购物商场当多用户登录时,如果都是登录的同一个账号的话,会有意想不到的问题,由于还没学到socket编程以及IO阻塞,所以暂时不优化

2.信用卡查询账单时,我是直接打印的日志文件里的,这样大体没问题,但不怎么好看

 

以上问题,感兴趣的可以自己优化一下,其他方面基本上没啥问题,有问题还望指出

 

细心的朋友你会发现,我的项目实战篇也是由易到难的,从零基础开始的,前面的项目很简单,不用函数都可以搞定,慢慢的开始使用到函数,下一篇项目实战也将从面向对象开始。然后前面基础篇漏掉的知识也会在实战篇中提出来,换句话就是利用项目实战,即把基础复习了,也把项目练好了,是不是想想就带劲,哈哈,唯一的不足就是,我知道我更博的时间太随意了,没办法啊,我也自学啊,还是那句,有时间就更新。不多说,大家都能把技术学好才是最终目的

 

转载于:https://www.cnblogs.com/Eeyhan/p/8342662.html


http://www.ppmy.cn/news/197188.html

相关文章

工匠精神消失的手机2020:衰落、变局、绝唱、破圈

文/智能相对论&#xff08;aixdlun&#xff09; 作者/郭锴 2015年&#xff0c;华为终端总裁余承东曾预言&#xff0c;未来四到五年&#xff0c;国内的智能手机品牌将只会剩余三家。彼时还处于群雄逐鹿时代&#xff0c;这个结论在当时看起来颇有些武断。但今天&#xff0c;202…

魅族应用市场之--自动化测试Umeng分享报错

打完包&#xff0c;用360加固完成&#xff0c;上传到魅族应用市场。 魅族反馈&#xff0c;测试化不通过&#xff0c;报错&#xff1a; {"brandName":"魅族","failMsg":"// CRASH: com.moreunion.zhenghao (pid 8391) // Short Msg: java.…

魅族pro7H节能优化手册

魅族pro7H节能优化手册 一、 使用前的准备 1、 软件&#xff1a;①tasker&#xff08;或者镧工具箱2.0&#xff09;②绿色守护③freezeyou!④禁用服务⑤block⑥autostarts⑦root explorer&#xff08;主要是用来找文件路径&#xff0c;不是必须的&#xff09;⑧supersu#⑨哔哩哔…

flyme android 7 root,魅族PRO7怎么Root?魅族PRO7一键ROOT权限获取图文教程(系统自带Root功能)...

ROOT大家都不会陌生&#xff0c;一般是指安卓手机获得最高管理权限。那么魅族PRO7怎么Root&#xff0c;今天小编主要详细介绍下魅族PRO7快速ROOT图文教程。值得一提的是&#xff0c;魅蓝手机ROOT比较简单&#xff0c;因为系统自带了ROOT工具&#xff0c;无需借助第三方工具即可…

自动搜索调频收音机

2006-04-23 22:32:09 自动搜索调频收音机 自动搜索调频收音机与普通调频收音机的主要区别就在于它们的调台方式不同。自动搜索调频收音机采用电调谐方式选择电台&#xff0c;省去了可变电容器&#xff0c;设置了“搜索”和“复位”两个轻触式按钮。使用时只要按下搜索按钮&…

gnuradio+b210实现FM收音机

gnuradiob210实现FM收音机 环境介绍FM接收1 Flow Graph2 变量参数 FM发射1 Flow Graph2 变量参数 环境介绍 NameVersiongnuradio3.7.14.0uhd3.15.0.0ubuntu18.04usrpb210 参考 https://www.ijedr.org/papers/IJEDR1702038.pdfAudio File Transmission using GNURADIO and USR…

超外差式收音机的工作原理

简单收音机为了提高灵敏度指标增加了高放级&#xff0c;但高放级级数的增加是有限度的&#xff0c;如果为了提高灵敏度而加多高放级&#xff0c;则不但统调因难&#xff0c;更易发生寄生振荡。另一个原因在于&#xff1a;晶体管电路对高中低频带的表现是不同的&#xff0c;这就…

收音机RDS功能介绍

什么叫RDS&#xff1f;收音机RDS功能介绍 转自加加论坛&#xff1a; http://jiajiaradio.5d6d.com/thread-108-1-1.html 从网上搜来的字面解释是&#xff1a;RDS是英国BBC广播公司开发的一种特殊的无线电广播&#xff0c;称”无线数据广播系统“&#xff08;Radio Data System&…