'''
项目启动入口
'''
import os
import sys
# 将项目的根目录,添加到sys.path中
sys.path.append(
os.path.dirname(os.path.dirname(__file__))
)
from core import src
if __name__ == '__main__':
src.run()
'''
此处存放核心业务逻辑代码
'''
from db import db_hanlder
from lib import common
import time
# login_user: 若能进入该函数,证明用户已登录,能获取当前用户名
login_user = None
# 注册功能
def register():
print('注册功能执行中...')
while True:
username = input('请输入用户名 (输入q退出): ').strip()
# if username == 'q':
# break
# 1) 先校验用户是否存在
# 涉及数据的操作: 调用查看数据功能 ---> select
# 给select函数传入当前输入的用户名,用于判断该用户是否存在
# user_data ---> [user, pwd, bal] or None
user_data = db_hanlder.select(username)
# 2)若存在,让用户重新输入
if user_data:
print('当前输入的用户已存在,请重新输入!')
continue
password = input('请输入密码: ').strip()
re_password = input('请确认密码: ').strip()
# 3)两次密码是否一致的校验
if password == re_password:
# 4) 将当前用户数据写入文件中
db_hanlder.save(username, password)
print(f'用户[{username}]注册成功!')
break
else:
print('两次密码不一致,请重新输入!')
# 登录功能
def login():
print('登录功能执行中...')
while True:
username = input('请输入用户名 (输入q退出): ').strip()
# 1) 查看当前用户是否存在 [user, pwd, balance] or None
user_data = db_hanlder.select(username)
# 2)若不存在,让用户重新输入
if not user_data:
print('当前输入的用户不存在,请重新输入!')
continue
password = input('请输入密码: ').strip()
# 3)校验用户输入的密码是否与db.txt中的密码一致
if password == user_data[1]:
# 4)用户登录后记录登录状态
global login_user
login_user = username
print(f'用户[{username}]登录成功!')
break
else:
print('密码错误,登录失败!')
# 充值功能
@common.login_auth
def recharge():
print('充值功能执行中...')
while True:
# 1) 让用户输入充值金额
balance = input('请输入充值金额: ').strip()
# 2)判断用户输入的金额是否是数字
if not balance.isdigit():
print('请输入数字!')
continue
balance = int(balance) # 100
# 3) 修改当前用户的金额
# 3.1) 获取当前用户的数据
user, pwd, bal = db_hanlder.select(login_user) # [user, pwd, bal]
# 3.2) 先获取用户 "修改前" 的数据
old_data = f'{user}:{pwd}:{bal}'
# 3.3) 修改当前用户金额,做加钱操作
bal = int(bal)
bal += balance
# 3.4) 拼接 "修改后" 的当前用户数据
# 此时bal的值已经被修改
# 'tank:123:0' ---> 'tank:123:100'
new_data = f'{user}:{pwd}:{bal}'
# 3.5)调用修改数据功能
# 'tank:123:0' ---> 'tank:123:100'
db_hanlder.update(old_data, new_data)
print(f'当前用户: [{login_user}] 充值金额 [{balance}元] 成功!')
# ending: 做充值日志记录
now_time = time.strftime('%Y-%m-%d %X')
log_data = f'时间: {now_time} 用户名: {login_user} 充值金额:{balance}'
print(log_data)
common.append_log(log_data)
break
# 小说阅读功能
@common.login_auth
def reader():
'''
1、写该功能之前,先将小说数据,存放在story_class.txt文件中
2、先将story_class.txt文件中数据,获取出来,解析成字典类型
:return:
'''
# 获取story_class.txt文件中的字典数据
# story_dic ---> {小说数据字典} ---> ''
story_dic = db_hanlder.get_all_story()
# 判断story_class.txt文件中是否有小说数据
if not story_dic:
print('没有小说,请联系管理员上传~~')
return
'''story_dic
{
"0":{
"0":["倚天屠狗记.txt",3],
"1":["沙雕英雄转.txt",10]
},
"1":{
"0":["令人羞耻的爱.txt",6],
"1":["二狗的妻子与大草原的故事.txt",5]
},
"2":{
"0":["矮跟落叶归根养猪护理传.txt",100],
"1":["矮跟在猪圈雨后的小故事.txt",500]
},
}
'''
while True:
# 1) 打印小说种类选择信息
print('''
=== 欢迎来到阅读小说功能主页 ===
0 玄幻武侠
1 都市爱情
2 高效养猪36技
============ end ============
''')
# 2)让用户输入小说类型编号
choice1 = input('请输入小说类型编号:').strip()
# 3)判断当前用户选择的编号是否存在
# 若输入有误则,重新输入
if choice1 not in story_dic:
print('输入有误,请重新输入!!!')
continue
# 4)获取当前小说类型中的所有小说数据
fiction_dic = story_dic.get(choice1) # choice1 == '1'
'''fiction_dic
{
"0":["令人羞耻的爱.txt",6],
"1":["二狗的妻子与大草原的故事.txt",5]
},
'''
# 5)打印当前类型的所有小说
for number, fiction_list in fiction_dic.items():
name, price = fiction_list
print(f'小说编号: [{number}] 小说名字: [{name}] 小说价格: [{price}]')
# 6)让用户选择选择需要购买的小说
while True:
choice2 = input('请输入需要购买的小说编号: ').strip()
if choice2 not in fiction_dic:
print('输入有误,请重新输入!!!')
continue
# name, price = ["二狗的妻子与大草原的故事.txt",5]
# name --> 小说名字 price ---> 小说单价
name, price = fiction_dic.get(choice2)
# 7)让用户输入y选择是否购买商品
choice3 = input(f'当前选择的小说名为: [{name}],商品单价为: [{price}], 请输入y购买,或者退出程序:').strip()
# 8)判断用户输入的是否是y
if choice3 == 'y':
# 9)校验当前用户的金额是否 >= 小说单价
# 9.1)获取当前用户金额
user, pwd, bal = db_hanlder.select(login_user)
# 9.2)判断金额
# 当前用户金额
bal = int(bal)
# 小说单价
price = int(price)
if bal < price:
print('穷鬼,请先充值~~~')
break
# 10 开始扣费
# 10.1)拼接用户修改前的数据
old_data = f'{user}:{pwd}:{bal}'
# 10.2) 开始对用户金额做减钱操作
bal -= price
# 10.)拼接用户修改后的数据
new_data = f'{user}:{pwd}:{bal}'
db_hanlder.update(old_data, new_data)
print('当前小说购买成功,自动打开小说阅读~~')
# 11) 调用获取想说详细信息数据
fiction_data = db_hanlder.show_fiction_data(name)
print(
f'''
==== 当前小说数据如下 ====
{fiction_data}
'''
)
# 12) 记录购买成功日志
now_time = time.strftime('%Y-%m-%d %X')
log_data = f'时间: {now_time} 用户名: {login_user} 消费金额:{price}'
print(log_data)
common.append_log(log_data)
break
break
# 函数字典
func_dic = {
'0': register,
'1': login,
'2': recharge,
'3': reader,
}
# 启动函数
def run():
'''
# 一:程序运行开始时显示
0 账号注册
1 账号登录
2 充值功能
3 阅读小说
'''
while True:
print('''
===== 小说阅读器欢迎您 =====
0 账号注册
1 账号登录
2 充值功能
3 阅读小说
========== end ==========
''')
# choice --> '1'
choice = input('请输入功能编号 (温馨提示[输入q退出]): ').strip()
if choice == 'q':
break
# 判断用户输入的编号是否在函数字典中
if choice not in func_dic:
print('当前编号有误,请重新输入!')
continue
# func_dic.get('1')() --> register函数对象 ---> register()
func_dic.get(choice)()
'''
此处存放公共功能
'''
from conf import settings
# 登录认证装饰器
def login_auth(func):
# 解决问题: 循环导入问题
from core import src
def inner(*args, **kwargs):
if src.login_user:
res = func(*args, **kwargs)
return res
else:
print('未登录,不允许使用特殊功能, 请先登录~~~')
src.login()
return inner
# 记录日志,应该放在公共功能中
def append_log(log_data):
# 写入日志数据
with open(settings.LOG_PATH, 'a', encoding='utf-8') as f:
f.write(log_data + '\n')
'''
用于存放操作数据代码
'''
from conf import settings
import os
# 查看数据
def select(username):
'''
- 接收用户输入的用户名
- 若该用户存在,则返回当前用户的所有数据
- 若不存在,则返回None
:param username:
:return:
'''
with open(settings.DB_TXT_PATH, 'r', encoding='utf-8') as f:
# 获取db.txt文件中的每一行数据
for line in f:
# 在每一行中,判断接收过来的用户名是否存在db.txt文件中
if username in line:
# 若用户存在,则在当前行中提取该用户的所有数据
# user_data ---> [user, pwd, bal]
user_data = line.strip().split(':')
# 将当前用户数据,返回给调用者
return user_data
# 保存数据
def save(username, password, balance=0):
'''
:param username: 注册用户名
:param password: 注册密码
:param balance: 注册用户初始金额设置为默认值
:return:
'''
with open(settings.DB_TXT_PATH, 'a', encoding='utf-8') as f:
f.write(f'{username}:{password}:{balance}\n')
# 更新数据
def update(old_data, new_data):
'''
将旧数据old_data:'tank:123:0' 替换成new_data:---> 新数据'tank:123:100'
:return:
'''
# 1) 拼接新的文件路径
new_path = os.path.join(
settings.DB_PATH, 'new.txt'
)
# 2) 读取db.txt文件中数据进行修改,写入到新文件new.txt文件中,再更换为db.txt文件名
with open(settings.DB_TXT_PATH, 'r', encoding='utf-8') as r_f, \
open(new_path, 'w', encoding='utf-8') as w_f:
# 2.1)新旧数据替换
# python终极奥秘: 尽量让代码更简洁
all_user_data = r_f.read()
all_user_data = all_user_data.replace(old_data, new_data)
# 2.2)将新数据写入新文件中
w_f.write(all_user_data)
# 3) 文件名的修改
# os.remove() 可以不写
# 这一步db.txt会将原来的覆盖掉
os.rename(new_path, settings.DB_TXT_PATH)
# 获取小说字典数据
def get_all_story():
with open(settings.STORY_PATH, 'r', encoding='utf-8') as f:
story_dic = eval(f.read())
return story_dic
# 查看单本小说
def show_fiction_data(fiction_name):
# 获取小说路径
fiction_path = os.path.join(
settings.FICTION_DIR, fiction_name
)
# 打开文件,获取文件数据,并返回给用户展示
with open(fiction_path, 'r', encoding='utf-8') as f:
fiction_data = f.read()
return fiction_data
'''
此处存放固定的配置信息
'''
import os
# 获取项目根目录reader_sys根目录
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
# 获取db目录路径
# /python相关/python_files/01 python班级/reader_sys
# /python相关/python_files/01 python班级/reader_sys/db
DB_PATH = os.path.join(BASE_PATH, 'db')
# 获取db.txt的根目录
DB_TXT_PATH = os.path.join(DB_PATH, 'db.txt')
# story_class.txt文件目录路径
STORY_PATH = os.path.join(DB_PATH, 'story_class.txt')
# 小说存放目录
FICTION_DIR = os.path.join(DB_PATH, 'fictions')
# 日志文件的路径
LOG_PATH = os.path.join(BASE_PATH, 'log', 'log.txt')