购物商城
1 #!/usr/bin/env python 2 """ 3 购物系统 4 5 aim : 6 1. 登录-三次失败锁定; 账户锁定可通过验证码解锁重新设置密码 7 2. 展示商品-分页,当前页焦点 8 3. 购物记录-文件,用户退出会生成一个已购物日志文件. 9 4. 余额浮点数 10 5. 查看购物车支持模糊查询,不区分大小写 11 6. 区分游客和正式用户;游客可直接浏览商品,可直接加入购物车;但购买需登录 12 7. 游客浏览只有登录和购物车两个选项 13 8. 登录后,取消登录选项,增加结账,充值和退出三个选项 14 9. 游客状态的购物车,在登录后仍然保留;可直接进行结账操作. 15 10. 用户登录后,选购商品,不结账,购物车保存. 退出下次登录购物车仍然有上次的记录,结账后清空. 16 11. 购物车实现删除功能. 17 18 need : 19 1. 用户输入 20 2. 商品信息文件 21 3. 用户信息文件 22 23 待完善: 24 1. 终端输出有待优化 25 { 26 1. 格式化字符串 27 2. 提示语 28 } 29 4. None 30 """ 31 32 33 # vars and funcs 34 35 # 格式化打印清单; 返回消费总金额 36 def show_card(dic): 37 sum_money = 0 38 top_str = ">>您选购的商品列表<<" 39 print('\n' + top_str.center(100, ' ')) 40 print("-" * 100) 41 print("{}\t\t{}\t\t{}\t\t{}".format("小计", "数量", "单价", "商品").expandtabs(10)) 42 print("-" * 100) 43 for ITEM in dic: 44 sum_money += float(get_price(ITEM)) * int(dic[ITEM]) 45 print('%.2f\t\t%d\t\t%.2f\t\t%s'.expandtabs(10) % ( 46 float(get_price(ITEM)) * int(dic[ITEM]), int(dic[ITEM]), 47 float(get_price(ITEM)), ITEM)) 48 print("-" * 100) 49 return sum_money 50 51 52 # 判断是否是浮点数 53 def is_floated(para): 54 try: 55 float(para) 56 return True 57 except: 58 return False 59 60 61 # 生成随机验证码 62 def get_random_code(): 63 import random 64 random_code = '' 65 for i in range(4): 66 cur = random.randrange(0, 4) 67 if cur != i: 68 temp = chr(random.randint(65, 90)) 69 else: 70 temp = random.randint(0, 9) 71 random_code += str(temp) 72 return random_code 73 74 75 # 解锁账户 76 def unlock_account(username): 77 print('\n解锁账户须进行以下验证') 78 while True: 79 code_random = get_random_code() 80 print('验证码: ', code_random) 81 user_code = input('请输入上述的验证码: ') 82 if str(user_code).strip() == code_random: 83 print('验证通过,请重新设置密码.') 84 new_pass = input('请输入新密码: ') 85 confirm_pass = input('请再输一遍密码: ') 86 if new_pass == confirm_pass: 87 for user_item in user_detail_list: 88 if user_item['name'] == username: 89 user_item['pwd'] = confirm_pass 90 user_item['times'] = 0 91 return True 92 else: 93 print('输入错误,请重新设置.') 94 else: 95 print('验证码输入错误,请重新输入.') 96 97 98 # 判断是否有登录在线用户, 返回用户的姓名,登录状态,总金额,用户列表在总用户列表里面的下标 99 def user_is_auth(): 100 rt_list = [] 101 for user_dic in user_detail_list: 102 if user_dic['status'] == 1: 103 rt_list.append(user_dic['name']) 104 rt_list.append(user_dic['status']) 105 rt_list.append(user_dic['money']) 106 rt_list.append(user_detail_list.index(user_dic)) 107 return rt_list 108 109 110 # 返回10条记录, 可根据page_numb来展示 111 def get_ten_record(pas_list, page_numb=1): 112 return_list = [] 113 start_num = (int(page_numb) - 1) * 10 114 end_num = int(page_numb) * 10 115 for ITEM in range(start_num, end_num): 116 if ITEM < len(pas_list): 117 return_list.append(pas_list[ITEM]) 118 return return_list 119 120 121 # 获取商品价格 122 def get_price(goods_name): 123 with open('goods.info', 'r', encoding='utf-8') as file_goods: 124 for goods in file_goods.readlines(): 125 goods = goods.strip().split('---') 126 if goods_name in goods: 127 return goods[-1] 128 129 130 # 打印10条记录 131 def show_ten_record(return_list, num): 132 print('\n%s\t\t%s\t\t%s'.expandtabs(10) % ('商品ID', '商品价格', '商品名称')) 133 print('-' * 80) 134 for K, ITEM in enumerate(return_list, 1000 + 10 * (num - 1) + 1): 135 print('%d\t\t%.2f¥\t\t%s'.expandtabs(10) % (K, float(ITEM[1]), ITEM[0])) 136 id_list.append(K) 137 print() 138 print_str = '' 139 for i in range(1, end_with): 140 if i != end_with - 1: 141 print_str = print_str + ' ' + str(i) + ' | ' 142 else: 143 print_str = print_str + ' ' + str(i) + ' ' 144 print(print_str.replace(' ' + str(num) + ' ', ' < ' + str(num) + ' > ') + '\n') 145 146 147 # ########################## 用户信息文件处理 start ########################## 148 # 存放用户信息 149 # user_detail_list = [ 150 # { 151 # 'name': 'alex', 152 # 'pwd': 12121212, 153 # 'times': 2, 154 # 'money': 120000.00, 155 # 'status': 0 156 # } 157 # ... 158 # ] 159 user_detail_list = [] 160 161 with open('db', 'r') as f_user: 162 for user_info in f_user.readlines(): 163 user_detail = user_info.split('|') 164 user_detail_list.append({ 165 'name': user_detail[0].strip(), 166 'pwd': user_detail[1].strip(), 167 'times': user_detail[2].strip(), 168 'money': user_detail[3].strip(), 169 'status': 0 # 登录状态,未登录0,登录1 170 }) 171 172 # 用户消费记录列表 173 record_user_crash = [] 174 # ########################## 用户信息文件处理 end ########################## 175 # ########################## 商品信息文件处理 start ########################## 176 # 将商品信息从文件里面取出来,每行一个列表,存在列表里面 177 book_all_list = [] 178 with open('goods.info', 'r', encoding='utf-8') as f_goods: 179 for line in f_goods.readlines(): 180 book_list = line.strip().split('---') 181 book_all_list.append(book_list) 182 183 # 定义空列表,用来存放展示的商品ID,由于可变;因此选择list 184 id_list = [] 185 # 定义页码元组 186 lens = len(book_all_list) 187 if lens % 10: 188 end_with = lens // 10 + 2 189 else: 190 end_with = lens // 10 + 1 191 pn_list = tuple(range(1, lens)) 192 # 定义用户操作行为元组 193 uc_tuple = ('登录', '购物车') 194 uc_login_tup = ('充值', '结账', '购物车', '退出') 195 196 # 定义缺省购物车 197 # 购物车设计 198 # default_goods_dic = { 199 # '老男孩Mysql私房菜': 3 200 # } 201 default_goods_dic = {} 202 # ########################## 商品信息文件处理 end ########################## 203 # main start 204 print('''\n 205 欢迎来到老男孩购物商城 206 提示: 207 a. 您可以直接输入商品ID将商品加入购物车 208 b. 您也可以直接登录、查看购物车 209 c. 您也可以输入页码进行翻页 210 ''') 211 print('商品首页') 212 213 page_num = 1 214 while True: 215 # 默认显示首页 216 show_ten_record(get_ten_record(book_all_list, page_num), page_num) 217 218 # 获取登录状态 219 res_auth = user_is_auth() 220 221 # 登录判断 222 if res_auth: 223 # 用户文件名 - 字符串 224 user_record_file = user_is_auth()[0] + '.info' 225 226 # 用户登录,生成用户所属购物车文件 227 user_choice_file = user_is_auth()[0] + '.car' 228 import os 229 230 if os.path.exists(user_choice_file): 231 if os.path.getsize(user_choice_file): 232 with open(user_choice_file, 'r') as fw_shop: 233 for line in fw_shop.readlines(): 234 shop_record = line.strip().split('---') 235 default_goods_dic[shop_record[0]] = shop_record[-1] 236 os.remove(user_choice_file) 237 # print(default_goods_dic) 238 # 一次性操作,登录后去掉登录显示 239 uc_temp = uc_login_tup 240 # 打印功能列表 241 for k, v in enumerate(uc_temp, 101): 242 print('{0}. {1}'.format(k, v)) 243 244 user_choice_num = input('\n欢迎你, ' + res_auth[0] + ' 请开始你的表演: ') 245 else: 246 # 未登录时,显示登录 247 uc_temp = uc_tuple 248 # 打印功能列表 249 for k, v in enumerate(uc_temp, 101): 250 print('{0}. {1}'.format(k, v)) 251 252 user_choice_num = input('\n游客,您好; 请开始你的表演: ') 253 254 if user_choice_num.isdigit(): 255 user_num = int(user_choice_num) 256 if user_num in pn_list: 257 page_num = user_num 258 print('\n当前您正在浏览第 {} 页'.format(page_num)) 259 elif 100 < user_num < 105: 260 # 登录 默认显示 261 if uc_temp[user_num - 100 - 1] == '登录': 262 print('login') 263 flag = True 264 # 退出次数 265 exit_flag = 3 266 # main process 267 while flag: 268 user_name = input("用户名: ") 269 # 遍历用户信息列表 270 for item in user_detail_list: 271 # 判断用户名是否存在 272 if user_name == item['name']: 273 # 用户存在判断是否锁定 274 if int(item['times']) < exit_flag: 275 user_pwd = input("密码: ") 276 # 校验密码 277 if user_pwd == item['pwd']: 278 print('登录成功\n\n') 279 # 更新字典 280 item['times'] = 0 281 # 写入登录状态 282 item['status'] = 1 283 # 更新while循环标志位 284 flag = False 285 # 退出for循环 286 break 287 else: 288 print('密码错误') 289 # 更新字典 290 item['times'] = int(item['times']) + 1 291 # 退出for循环,继续输入用户名 292 break 293 else: 294 print("用户已经锁定") 295 while True: 296 lock_choice = input('1. 更换账户\t2. 找回密码\n >> ') 297 if lock_choice.isdigit(): 298 if int(lock_choice) == 1: 299 break 300 elif int(lock_choice) == 2: 301 if unlock_account(user_name): 302 print('重置密码成功,请重新登录') 303 break 304 break 305 else: 306 print('用户名不存在') 307 308 # 充值 登录后显示 309 if uc_temp[user_num - 101] == '充值': 310 charge_money = input('请输入要充值的金额: ') 311 if is_floated(charge_money): 312 charge_money = float(charge_money) 313 item_money = float(res_auth[2]) 314 item_money += charge_money 315 user_detail_list[res_auth[-1]]['money'] = item_money 316 print('您已成功充值%.2f元, 账户余额%.2f' % (charge_money, item_money)) 317 else: 318 print('输入无效') 319 320 # 结账 登录后显示 321 if uc_temp[user_num - 101] == '结账': 322 import time 323 324 crash_money = 0 325 if default_goods_dic: 326 crash_money = show_card(default_goods_dic) 327 if float(crash_money) > float(res_auth[2]): 328 print('您本次消费总共:%.2f ;余额不足,您至少需要充值 %.2f 人民币!' % (crash_money, crash_money - float(res_auth[2]))) 329 else: 330 user_detail_list[res_auth[-1]]['money'] = float(res_auth[2]) - crash_money 331 print('您本次消费总共:%.2f ;\n\t\t账户余额: %.2f !' % (crash_money, float(res_auth[2]) - crash_money)) 332 # 将购物记录记录到文件 333 for item in default_goods_dic: 334 each_str = u'{}在{}购买了{}本单价为{}人民币的{}\n'.format( 335 user_is_auth()[0], time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), 336 default_goods_dic[item], get_price(item), item) 337 record_user_crash.append(each_str) 338 # 结账完毕,清空购物车 339 default_goods_dic.clear() 340 else: 341 print('购物车为空') 342 343 # 查看购物车 默认显示 支持删除 344 if uc_temp[user_num - 101] == '购物车': 345 crash_money = 0 346 if default_goods_dic: 347 while True: 348 show_card(default_goods_dic) 349 crash_choice = input('结账请先登录, 查询请输入S/s, 删除请输入D/d, 返回请按Q/q') 350 if crash_choice.strip().lower() == 's': 351 while True: 352 sc_name = input('请输入要查询的商品名[支持模糊查询,退出请按Q/q]: ') 353 if sc_name.strip().lower() != 'q': 354 for item in default_goods_dic.keys(): 355 if sc_name.lower() in item.lower() and sc_name.strip() != '': 356 print('%.2f\t\t%d\t\t%.2f\t\t%s'.expandtabs(20) % ( 357 float(get_price(item)) * default_goods_dic[item], 358 default_goods_dic[item], 359 float(get_price(item)), item)) 360 else: 361 break 362 elif crash_choice.strip().lower() == 'd': 363 while True: 364 if default_goods_dic: 365 del_name = input('请输入要删除的商品名称, 退出请按Q/q: ') 366 if del_name.strip().lower() != 'q': 367 try: 368 v = default_goods_dic.pop(del_name) 369 print('您已经从购物车移除{}本{}'.format(v, del_name)) 370 except KeyError: 371 print('移除失败') 372 else: 373 break 374 else: 375 print('购物车已被清空') 376 elif crash_choice.strip().lower() == 'q': 377 break 378 else: 379 print('购物车为空') 380 381 # logout 382 if uc_temp[user_num - 101] == '退出': 383 print('欢迎下次光临') 384 # 更新用户status 385 user_detail_list[user_is_auth()[-1]]['status'] = 0 386 if default_goods_dic: 387 with open(user_choice_file, 'w') as fw_record: 388 for item in default_goods_dic.items(): 389 fw_record.writelines(item[0] + '---' + str(item[1]) + '\n') 390 391 break 392 393 elif user_num in id_list: 394 # # 添加商品到购物车,若未登录则添加到默认购物车dict,登录成功则创建用户自己的购物车dict 395 # 获取页码数 396 # page_num = int(str(user_num)[-2]) + 1 397 page_num = int(str(user_num - 1)[-2]) + 1 398 # 获取商品列表下标 399 goods_index = int(str(user_num)[-1]) - 1 400 # 得到当前页当前id的商品信息 list 401 goods_info = get_ten_record(book_all_list, page_num)[goods_index] 402 # print(good_info) 403 # 往用户购物车添加记录,若无登录则使用default 404 if goods_info[0] not in default_goods_dic: 405 default_goods_dic[goods_info[0]] = 1 406 else: 407 default_goods_dic[goods_info[0]] += 1 408 print('\n提示: 您已成功将一本 {} 添加到购物车, 目前数量 {} 本'.format(goods_info[0], default_goods_dic[goods_info[0]])) 409 else: 410 print('表演不满意,请重新开始你的表演\n') 411 412 # 最后,将用户信息写入文件 413 # 写入文件 414 with open('db', 'w') as f_user: 415 for item in user_detail_list: 416 f_user.truncate() 417 item_str = '{name}|{pwd}|{times}|{money}|{status}\n'.format_map(item) 418 # print(item_str) 419 f_user.writelines(item_str) 420 421 # 写入用户的购物记录 422 with open(user_record_file, 'a') as uw_file: 423 uw_file.writelines(record_user_crash) 424 record_user_crash.clear()