洗礼灵魂,修炼python(82)--全栈项目实战篇(10)—— 信用卡+商城项目(模拟京东淘宝)
本次项目相当于对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
画得比较简单,每个文件都有备注是干嘛的。
其实这个没什么难度,流程还是那些,登录验证,交易,更新数据,结束
流程图:
剩下的就是每个文件的编写,以及如何让这些文件联系起来了
这里说个知识点:
1 2 3 4 5 6 | # 将当前py文件的上级文件夹目录的路径添加到模块索引列表内 import sys,os path = os.path.dirname(__file__) sys.path.append(path) |
以上的代码则可以把你的文件作为py文件导入并且不怕因为文件路径被修改而导致导入失败了
代码:
项目包下载链接:传送门
需要的文件:
card.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/19 0019 21:41 import os,sys base_dir = os.path.dirname(os.path.dirname(__file__)) sys.path.append(base_dir) from libs import main if __name__ = = '__main__' : main.run() |
main.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/19 0019 21:43 import os,sys base_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_DIR with 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: %s balance: %s ''' % (corrent_accdata[' id '],corrent_accdata[' credit '],corrent_accdata[' balance'])) back_flag = False while not back_flag: repay_amount = input ( "\033[36;1mplease enter amount or 'b' to back:\033[0m" ).strip() if repay_amount = = 'b' : back_flag = True print () #此处的打印空是为了换行美观,否则日志输出会和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: %s balance: %s ''' % (corrent_accdata[' id '],corrent_accdata[' credit '],corrent_accdata[' balance'])) back_flag = False while not back_flag: draw_amount = input ( "\033[36;1mplease enter amount or 'b' to back:\033[0m" ).strip() if draw_amount = = 'b' : back_flag = True if 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: %s balance: %s ''' % (corrent_accdata[' id '],corrent_accdata[' credit '],corrent_accdata[' balance'])) back_flag = False while not back_flag: transfer_amount = input ( "\033[36;1mplease enter amount or 'b' to back:\033[0m" ).strip() if transfer_amount = = 'b' : back_flag = True if 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;1m 1.账户信息 2.还款 3.取款 4.转账 5.查询账单 6.退出\033[0m''' option_dict = { '1' :userinfo, '2' :repay, '3' :draw, '4' :transfer, '5' :select, '6' :logout } exit_flag = False while 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' ] = userdata optionlist(userdata) |
logger.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/19 0019 21:54 import logging from conf import settings def 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) # 把文件型日志和输出型日志对象添加进logger logger.addHandler(fh) logger.addHandler(sh) return logger |
auth.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/19 0019 21:53 import json,os,time from conf import settings from libs import db def 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_data else : 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 = 0 while 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' ] = True data[ 'account_id' ] = userid return userauth count + = 1 else : logobj.error( '\033[31;1maccount [%s] too many login attempts\033[0m' % userid) exit() |
accounts.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/20 0020 22:38 from conf import settings from libs import db import json def 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_accdata def 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/20 0020 17:50 from conf import settings from libs import accounts def 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 + interest elif settings.TRAN_TYPE[trantype][ 'action' ] = = 'minus' : new_balance = old_balance - amount - interest if new_balance < 0 : print ( "\033[31;1maccount [%s] balance is not sufficient to pay [%s]!\033[0m" % (account_data[ 'id' ],amount + interest)) return account_data[ 'balance' ] = new_balance accounts.dump_accdata(account_data) logobj.info( 'account:%s - transaction:%s - amount:%s - interest:%s' % (account_data[ 'id' ],trantype,amount,interest)) return account_data else : print ( '\033[31;1mTransaction type [%s] is not exist!\033[0m' % trantype) |
settings.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/19 0019 21:56 import 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/19 0019 22:51 def 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_path def ml_db(parms): pass def mo_db(parms): pass def oe_db(parms): pass def 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/20 0020 15:43 import json,sys,os,datetime base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) sys.path.append(base_dir) from conf import settings from libs import db path = 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' ] = id enroll_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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | #!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2018/1/21 0024 17:44 import sys,json,os from collections import Counter base_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_path while 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 = True 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 return 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' ] = salary with 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 salary for 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 - = gprice print ( '\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' ) break elif shopping = = 'b' : #购买结束,到收银台结账 print ( '\033[32;1m已返回上一级\033[0m\n' ) break else : 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:
1 | { "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:
1 | { "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:
1 | { "yang" : "abc" , "id" : 62285589 } |
ling.json:
1 | { "ling" : "123" , "id" : 62285580 } |
运行效果:
运行card.py:
(部分截图)
详细结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | please enter your card's id : 62285589 enter your password:abc 1. 账户信息 2. 还款 3. 取款 4. 转账 5. 查询账单 6. 退出 please enter the option number: 2 - - - - - - - - - - user 62285589 bill - - - - - - - - - - creadit: 15000 balance: 16022.05 please enter amount or 'b' to back: 500 new 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 integer 1. 账户信息 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 : 15000 1. 账户信息 2. 还款 3. 取款 4. 转账 5. 查询账单 6. 退出 please enter the option number: 3 - - - - - - - - - - user 62285589 bill - - - - - - - - - - creadit: 15000 balance: 16522.05 please 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 integer 1. 账户信息 2. 还款 3. 取款 4. 转账 5. 查询账单 6. 退出 please enter the option number: 4 - - - - - - - - - - user 62285589 bill - - - - - - - - - - creadit: 15000 balance: 16417.05 please 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 integer 1. 账户信息 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.0 2018 - 01 - 21 20 : 25 : 43 , 037 - transaction - INFO - account: 62285589 - - transaction:draw - - amount: 400.0 - - interest: 20.0 2018 - 01 - 21 20 : 27 : 08 , 946 - transaction - INFO - account: 62285589 - - transaction:draw - - amount: 400.0 - - interest: 20.0 2018 - 01 - 21 20 : 31 : 55 , 979 - transaction - INFO - account: 62285589 - transaction:transfer - amount: 100.0 - interest: 5.0 2018 - 01 - 24 17 : 03 : 06 , 773 - transaction - INFO - account: 62285589 - transaction:repay - amount: 500.0 - interest: 0.0 2018 - 01 - 24 17 : 04 : 52 , 005 - transaction - INFO - account: 62285589 - transaction:draw - amount: 100.0 - interest: 5.0 2018 - 01 - 24 17 : 05 : 11 , 616 - transaction - INFO - account: 62285589 - transaction:transfer - amount: 200.0 - interest: 10.0 1. 账户信息 2. 还款 3. 取款 4. 转账 5. 查询账单 6. 退出 please enter the option number: 6 account [ 62285589 ] quit... |
运行shopping.py:
详细结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | - - - - - - - 欢迎光临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.信用卡查询账单时,我是直接打印的日志文件里的,这样大体没问题,但不怎么好看
以上问题,感兴趣的可以自己优化一下,其他方面基本上没啥问题,有问题还望指出
细心的朋友你会发现,我的项目实战篇也是由易到难的,从零基础开始的,前面的项目很简单,不用函数都可以搞定,慢慢的开始使用到函数,下一篇项目实战也将从面向对象开始。然后前面基础篇漏掉的知识也会在实战篇中提出来,换句话就是利用项目实战,即把基础复习了,也把项目练好了,是不是想想就带劲,哈哈,唯一的不足就是,我知道我更博的时间太随意了,没办法啊,我也自学啊,还是那句,有时间就更新。不多说,大家都能把技术学好才是最终目的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】