2025-04-09 17:14:37 +08:00
|
|
|
|
import math
|
|
|
|
|
|
|
2025-03-19 01:16:08 +08:00
|
|
|
|
from zhenxun.services.log import logger
|
2025-03-19 18:00:50 +08:00
|
|
|
|
from zhenxun.utils.image_utils import ImageTemplate
|
2025-03-19 01:16:08 +08:00
|
|
|
|
|
2025-06-06 10:56:22 +08:00
|
|
|
|
from ..config import g_sResourcePath, g_sTranslation
|
2025-04-28 19:27:16 +08:00
|
|
|
|
from ..dbService import g_pDBService
|
2025-03-17 18:07:25 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CShopManager:
|
|
|
|
|
|
@classmethod
|
2025-06-06 10:56:22 +08:00
|
|
|
|
async def getSeedShopImage(cls, filterKey: str | int = 1, num: int = 1) -> bytes:
|
2025-03-20 18:06:38 +08:00
|
|
|
|
"""获取商店页面
|
|
|
|
|
|
|
2025-05-28 19:48:12 +08:00
|
|
|
|
Args:
|
|
|
|
|
|
filterKey (str|int):
|
|
|
|
|
|
- 字符串: 根据关键字筛选种子名称
|
|
|
|
|
|
- 整数: 翻至对应页(无筛选)
|
|
|
|
|
|
num (int, optional): 当 filterKey 为字符串时,用于指定页码。Defaults to 1.
|
|
|
|
|
|
|
2025-03-19 18:00:50 +08:00
|
|
|
|
Returns:
|
2025-03-20 18:06:38 +08:00
|
|
|
|
bytes: 返回商店图片bytes
|
2025-03-19 18:00:50 +08:00
|
|
|
|
"""
|
2025-05-28 19:48:12 +08:00
|
|
|
|
# 解析参数:区分筛选关键字和页码
|
|
|
|
|
|
filterStr = None
|
|
|
|
|
|
if isinstance(filterKey, int):
|
|
|
|
|
|
page = filterKey
|
|
|
|
|
|
else:
|
|
|
|
|
|
filterStr = filterKey
|
|
|
|
|
|
page = num
|
2025-03-19 18:00:50 +08:00
|
|
|
|
|
2025-05-28 19:48:12 +08:00
|
|
|
|
# 表头定义
|
2025-05-12 17:28:33 +08:00
|
|
|
|
columnName = [
|
2025-03-19 18:00:50 +08:00
|
|
|
|
"-",
|
|
|
|
|
|
"种子名称",
|
2025-04-27 17:00:58 +08:00
|
|
|
|
"种子单价",
|
2025-03-19 18:00:50 +08:00
|
|
|
|
"解锁等级",
|
2025-04-27 10:52:28 +08:00
|
|
|
|
"果实单价",
|
2025-03-19 18:00:50 +08:00
|
|
|
|
"收获经验",
|
|
|
|
|
|
"收获数量",
|
2025-03-21 00:25:20 +08:00
|
|
|
|
"成熟时间(小时)",
|
2025-03-19 18:00:50 +08:00
|
|
|
|
"收获次数",
|
2025-06-06 10:56:22 +08:00
|
|
|
|
"是否可以上架交易行",
|
2025-03-19 18:00:50 +08:00
|
|
|
|
]
|
|
|
|
|
|
|
2025-05-28 19:48:12 +08:00
|
|
|
|
# 查询所有可购买作物,并根据筛选关键字过滤
|
2025-05-08 17:56:45 +08:00
|
|
|
|
plants = await g_pDBService.plant.listPlants()
|
2025-05-28 19:48:12 +08:00
|
|
|
|
filteredPlants = []
|
|
|
|
|
|
for plant in plants:
|
|
|
|
|
|
# 跳过未解锁购买的种子
|
2025-06-06 10:56:22 +08:00
|
|
|
|
if plant["isBuy"] == 0:
|
2025-05-08 17:56:45 +08:00
|
|
|
|
continue
|
2025-05-28 19:48:12 +08:00
|
|
|
|
# 字符串筛选
|
2025-06-06 10:56:22 +08:00
|
|
|
|
if filterStr and filterStr not in plant["name"]:
|
2025-05-28 19:48:12 +08:00
|
|
|
|
continue
|
|
|
|
|
|
filteredPlants.append(plant)
|
|
|
|
|
|
|
|
|
|
|
|
# 计算分页
|
|
|
|
|
|
totalCount = len(filteredPlants)
|
|
|
|
|
|
pageCount = math.ceil(totalCount / 15) if totalCount else 1
|
|
|
|
|
|
startIndex = (page - 1) * 15
|
2025-06-06 10:56:22 +08:00
|
|
|
|
pageItems = filteredPlants[startIndex : startIndex + 15]
|
2025-04-09 17:14:37 +08:00
|
|
|
|
|
2025-05-28 19:48:12 +08:00
|
|
|
|
# 构建数据行
|
|
|
|
|
|
dataList = []
|
|
|
|
|
|
for plant in pageItems:
|
|
|
|
|
|
# 图标处理
|
2025-03-19 18:00:50 +08:00
|
|
|
|
icon = ""
|
2025-05-12 17:28:33 +08:00
|
|
|
|
iconPath = g_sResourcePath / f"plant/{plant['name']}/icon.png"
|
|
|
|
|
|
if iconPath.exists():
|
|
|
|
|
|
icon = (iconPath, 33, 33)
|
2025-03-19 18:00:50 +08:00
|
|
|
|
|
2025-05-28 19:48:12 +08:00
|
|
|
|
# 交易行标记
|
2025-06-06 10:56:22 +08:00
|
|
|
|
sell = "可以" if plant["sell"] else "不可以"
|
|
|
|
|
|
|
|
|
|
|
|
dataList.append(
|
|
|
|
|
|
[
|
|
|
|
|
|
icon,
|
|
|
|
|
|
plant["name"], # 种子名称
|
|
|
|
|
|
plant["buy"], # 种子单价
|
|
|
|
|
|
plant["level"], # 解锁等级
|
|
|
|
|
|
plant["price"], # 果实单价
|
|
|
|
|
|
plant["experience"], # 收获经验
|
|
|
|
|
|
plant["harvest"], # 收获数量
|
|
|
|
|
|
plant["time"], # 成熟时间(小时)
|
|
|
|
|
|
plant["crop"], # 收获次数
|
|
|
|
|
|
sell, # 是否可上架交易行
|
|
|
|
|
|
]
|
|
|
|
|
|
)
|
2025-05-28 19:48:12 +08:00
|
|
|
|
|
|
|
|
|
|
# 页码标题
|
|
|
|
|
|
title = f"种子商店 页数: {page}/{pageCount}"
|
|
|
|
|
|
|
|
|
|
|
|
# 渲染表格并返回图片bytes
|
2025-03-19 18:00:50 +08:00
|
|
|
|
result = await ImageTemplate.table_page(
|
2025-04-09 17:14:37 +08:00
|
|
|
|
title,
|
2025-03-19 18:00:50 +08:00
|
|
|
|
"购买示例:@小真寻 购买种子 大白菜 5",
|
2025-05-12 17:28:33 +08:00
|
|
|
|
columnName,
|
|
|
|
|
|
dataList,
|
2025-03-19 18:00:50 +08:00
|
|
|
|
)
|
|
|
|
|
|
return result.pic2bytes()
|
2025-03-19 01:16:08 +08:00
|
|
|
|
|
|
|
|
|
|
@classmethod
|
2025-03-20 18:06:38 +08:00
|
|
|
|
async def buySeed(cls, uid: str, name: str, num: int = 1) -> str:
|
|
|
|
|
|
"""购买种子
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
uid (str): 用户Uid
|
|
|
|
|
|
name (str): 植物名称
|
|
|
|
|
|
num (int, optional): 购买数量
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
str:
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
2025-03-19 01:16:08 +08:00
|
|
|
|
if num <= 0:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["buySeed"]["notNum"]
|
2025-03-19 01:16:08 +08:00
|
|
|
|
|
2025-05-08 17:56:45 +08:00
|
|
|
|
plantInfo = await g_pDBService.plant.getPlantByName(name)
|
|
|
|
|
|
if not plantInfo:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["buySeed"]["error"]
|
2025-03-19 18:00:50 +08:00
|
|
|
|
|
2025-04-28 19:27:16 +08:00
|
|
|
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
2025-03-21 18:14:50 +08:00
|
|
|
|
|
2025-06-06 10:56:22 +08:00
|
|
|
|
if level[0] < int(plantInfo["level"]):
|
|
|
|
|
|
return g_sTranslation["buySeed"]["noLevel"]
|
2025-03-21 18:14:50 +08:00
|
|
|
|
|
2025-04-28 19:27:16 +08:00
|
|
|
|
point = await g_pDBService.user.getUserPointByUid(uid)
|
2025-06-06 10:56:22 +08:00
|
|
|
|
total = int(plantInfo["buy"]) * num
|
2025-03-19 18:00:50 +08:00
|
|
|
|
|
2025-06-06 10:56:22 +08:00
|
|
|
|
logger.debug(
|
|
|
|
|
|
f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}"
|
|
|
|
|
|
)
|
2025-03-19 18:00:50 +08:00
|
|
|
|
|
|
|
|
|
|
if point < total:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["buySeed"]["noPoint"]
|
2025-03-19 18:00:50 +08:00
|
|
|
|
else:
|
2025-04-28 19:27:16 +08:00
|
|
|
|
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
2025-03-19 18:00:50 +08:00
|
|
|
|
|
2025-05-28 19:48:12 +08:00
|
|
|
|
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["buySeed"]["errorSql"]
|
2025-04-07 18:52:27 +08:00
|
|
|
|
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["buySeed"]["success"].format(
|
|
|
|
|
|
name=name, total=total, point=point - total
|
|
|
|
|
|
)
|
2025-03-19 01:16:08 +08:00
|
|
|
|
|
2025-03-21 18:14:50 +08:00
|
|
|
|
@classmethod
|
|
|
|
|
|
async def sellPlantByUid(cls, uid: str, name: str = "", num: int = 1) -> str:
|
|
|
|
|
|
"""出售作物
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
uid (str): 用户Uid
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
str:
|
|
|
|
|
|
"""
|
2025-04-27 17:00:58 +08:00
|
|
|
|
if not isinstance(name, str) or name.strip() == "":
|
|
|
|
|
|
name = ""
|
|
|
|
|
|
|
2025-04-28 19:27:16 +08:00
|
|
|
|
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
2025-04-27 17:00:58 +08:00
|
|
|
|
if not plant:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["sellPlant"]["no"]
|
2025-03-21 18:14:50 +08:00
|
|
|
|
|
2025-04-27 17:00:58 +08:00
|
|
|
|
point = 0
|
|
|
|
|
|
totalSold = 0
|
2025-06-06 10:56:22 +08:00
|
|
|
|
isAll = num == -1
|
2025-03-21 18:14:50 +08:00
|
|
|
|
|
2025-04-27 17:00:58 +08:00
|
|
|
|
if name == "":
|
|
|
|
|
|
for plantName, count in plant.items():
|
2025-08-06 17:51:26 +08:00
|
|
|
|
isLock = await g_pDBService.userPlant.checkPlantLockByName(
|
|
|
|
|
|
uid, plantName
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if isLock:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2025-05-08 17:56:45 +08:00
|
|
|
|
plantInfo = await g_pDBService.plant.getPlantByName(plantName)
|
|
|
|
|
|
if not plantInfo:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2025-06-06 10:56:22 +08:00
|
|
|
|
point += plantInfo["price"] * count
|
2025-04-28 19:27:16 +08:00
|
|
|
|
await g_pDBService.userPlant.updateUserPlantByName(uid, plantName, 0)
|
2025-04-27 10:52:28 +08:00
|
|
|
|
else:
|
2025-04-27 17:00:58 +08:00
|
|
|
|
if name not in plant:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["sellPlant"]["error"].format(name=name)
|
2025-04-27 17:00:58 +08:00
|
|
|
|
available = plant[name]
|
|
|
|
|
|
sellAmount = available if isAll else min(available, num)
|
|
|
|
|
|
if sellAmount <= 0:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["sellPlant"]["error1"].format(name=name)
|
|
|
|
|
|
await g_pDBService.userPlant.updateUserPlantByName(
|
|
|
|
|
|
uid, name, available - sellAmount
|
|
|
|
|
|
)
|
2025-04-27 17:00:58 +08:00
|
|
|
|
totalSold = sellAmount
|
|
|
|
|
|
|
2025-05-08 17:56:45 +08:00
|
|
|
|
if name == "":
|
|
|
|
|
|
totalPoint = point
|
|
|
|
|
|
else:
|
|
|
|
|
|
plantInfo = await g_pDBService.plant.getPlantByName(name)
|
|
|
|
|
|
if not plantInfo:
|
|
|
|
|
|
price = 0
|
|
|
|
|
|
else:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
price = plantInfo["price"]
|
2025-05-08 17:56:45 +08:00
|
|
|
|
|
|
|
|
|
|
totalPoint = totalSold * price
|
|
|
|
|
|
|
2025-04-28 19:27:16 +08:00
|
|
|
|
currentPoint = await g_pDBService.user.getUserPointByUid(uid)
|
|
|
|
|
|
await g_pDBService.user.updateUserPointByUid(uid, currentPoint + totalPoint)
|
2025-04-27 17:00:58 +08:00
|
|
|
|
|
|
|
|
|
|
if name == "":
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["sellPlant"]["success"].format(
|
|
|
|
|
|
point=totalPoint, num=currentPoint + totalPoint
|
|
|
|
|
|
)
|
2025-03-21 18:14:50 +08:00
|
|
|
|
else:
|
2025-06-06 10:56:22 +08:00
|
|
|
|
return g_sTranslation["sellPlant"]["success1"].format(
|
|
|
|
|
|
name=name, point=totalPoint, num=currentPoint + totalPoint
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-03-19 01:16:08 +08:00
|
|
|
|
|
2025-03-19 18:00:50 +08:00
|
|
|
|
g_pShopManager = CShopManager()
|