种子商店新增筛选功能

This commit is contained in:
Art_Sakura 2025-05-28 19:48:12 +08:00
parent afa2259ad8
commit 7dc55bccf1
12 changed files with 411 additions and 92 deletions

4
.gitignore vendored
View File

@ -1 +1,3 @@
__pycache__
__pycache__
./config/sign_in.json

View File

@ -5,12 +5,42 @@
<a href="./LICENSE">
<img src="https://img.shields.io/badge/license-GPL3.0-FE7D37" alt="license">
</a>
<a href="https://www.python.org">
<img src="https://img.shields.io/badge/Python-3.10%2B-blue" alt="Python">
</a>
<a href="https://nonebot.dev/">
<img src="https://img.shields.io/badge/Nonebot-2.0.0%2B-black" alt="Nonebot">
</a>
<a href="https://github.com/zhenxun-org/zhenxun_bot">
<img src="https://img.shields.io/badge/zhenxun-0.2.4%2B-%23ECD9D3" alt="Python">
</a>
</p>
<p align="center">
[![tencent-qq](https://img.shields.io/badge/%E7%BE%A4-%E7%9C%9F%E5%AF%BB%E5%86%9C%E5%9C%BA%E6%B5%8B%E8%AF%95-%23FF99CC
)](https://qm.qq.com/q/7hsOD4rOw2)
</p>
你是说可以种地对吧🤔?
</div>
---
## 目录
- [真寻农场(zhenxun\_plugin\_farm)](#真寻农场zhenxun_plugin_farm)
- [目录](#目录)
- [如何安装](#如何安装)
- [使用指令](#使用指令)
- [更新日志(详细)](#更新日志详细)
- [用户方面](#用户方面)
- [代码方面](#代码方面)
- [待办事宜 `Todo` 列表](#待办事宜-todo-列表)
- [关于](#关于)
- [致谢](#致谢)
- [许可证](#许可证)
---
## 如何安装
@ -26,7 +56,7 @@
| --- | --- | --- |
| @小真寻 开通农场 | 首次开通农场 | |
| 我的农场币 | 查询农场币 | |
| 种子商店 [页数] | 查看种子商店 | 数量不填默认为1 |
| 种子商店 [筛选关键字] [页数] or [页数] | 查看种子商店 | 当第一个参数为非整数时,会默认进入筛选状态。页数不填默认为1 |
| 购买种子 [种子名称] [数量] | 购买种子 | 数量不填默认为1 |
| 我的种子 | 查询仓库种子 | |
| 播种 [种子名称] [数量] | 播种种子 | 数量不填默认将最大可能播种 |
@ -37,20 +67,23 @@
| @美波理 偷菜 | 偷别人的菜 | 每人每天只能偷5次 |
| 购买农场币 | 将真寻金币兑换成农场币 | 兑换比例默认为1:2 手续费默认20% |
| 更改农场名 [新的农场名] | 改名 |
| 农场签到 | 签到 | 需要注意,该项会从服务器拉取签到数据 |
---
## 更新日志[(详细)](./log/log.md)
用户方面
---
- 修复重大BUG该BUG会导致用户经验等级计算异常
- 修正种子价格,现在不会以单价的形式购买种子了,而是新增的种子价格
- 新增种子商店筛选功能如果没有BUG的话后续我的种子、我的作物等也会加入筛选功能
- 新增签到功能(测试
- 新增农场详述功能,能通过该功能更加详细的观看农场数据
- 修复了迁移旧数据库无法正常迁移的BUG
代码方面
---
- 彻底重构数据库但是不会像V1.1一样导致用户数据丢失
- 迁移部分代码结构,使文件名和代码功能更加匹配
- 加入事件机制采用类似Qt信号槽机制
- 修正了多阶段作物成长素材计算逻辑
- 修正了作物数据库字段错乱的问题
- 作物新增offset字段用于以后偏移坐标尚未加入代码 TODO
---
## 待办事宜 `Todo` 列表

View File

@ -22,7 +22,7 @@ __plugin_meta__ = PluginMetadata(
at 开通农场
我的农场
我的农场币
种子商店 [页数]
种子商店 [筛选关键字] [页数] or [页数]
购买种子 [作物/种子名称] [数量]
我的种子
播种 [作物/种子名称] [数量] (数量不填默认将最大可能播种
@ -34,6 +34,7 @@ __plugin_meta__ = PluginMetadata(
开垦
购买农场币 [数量] 数量为消耗金币的数量
更改农场名 [新农场名]
农场签到
""".strip(),
extra=PluginExtraData(
author="Art_Sakura",

View File

@ -1,3 +1,5 @@
import inspect
from nonebot.adapters import Event, MessageTemplate
from nonebot.rule import to_me
from nonebot_plugin_alconna import (Alconna, AlconnaMatch, AlconnaQuery, Args,
@ -125,7 +127,7 @@ diuse_farm = on_alconna(
Option("--all", action=store_true),
Subcommand("detail", help_text="农场详述"),
Subcommand("my-point", help_text="我的农场币"),
Subcommand("seed-shop", Args["num?", int], help_text="种子商店"),
Subcommand("seed-shop", Args["res?", MultiVar(str)], help_text="种子商店"),
Subcommand("buy-seed", Args["name?", str]["num?", int], help_text="购买种子"),
Subcommand("my-seed", help_text="我的种子"),
Subcommand("sowing", Args["name?", str]["num?", int], help_text="播种"),
@ -147,7 +149,7 @@ diuse_farm = on_alconna(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
image = await g_pFarmManager.drawFarmByUid(uid)
@ -164,7 +166,7 @@ diuse_farm.shortcut(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
info = await g_pFarmManager.drawDetailFarmByUid(uid)
@ -197,13 +199,35 @@ diuse_farm.shortcut(
)
@diuse_farm.assign("seed-shop")
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 1)):
async def _(session: Uninfo, res: Match[tuple[str, ...]]):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
image = await g_pShopManager.getSeedShopImage(num.result)
if res.result is inspect._empty:
raw = []
else:
raw = res.result
filterKey: str | int | None = None
page: int = 1
if len(raw) >= 1 and raw[0] is not None:
first = raw[0]
if isinstance(first, str) and first.isdigit():
page = int(first)
else:
filterKey = first
if len(raw) >= 2 and raw[1] is not None and isinstance(raw[1], str) and raw[1].isdigit():
page = int(raw[1])
if filterKey is None:
image = await g_pShopManager.getSeedShopImage(page)
else:
image = await g_pShopManager.getSeedShopImage(filterKey, page)
await MessageUtils.build_message(image).send()
diuse_farm.shortcut(
@ -214,7 +238,7 @@ diuse_farm.shortcut(
)
@diuse_farm.assign("buy-seed")
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1),):
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1)):
if not name.available:
await MessageUtils.build_message(
"请在指令后跟需要购买的种子名称"
@ -222,7 +246,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pShopManager.buySeed(uid, name.result, num.result)
@ -239,7 +263,7 @@ diuse_farm.shortcut(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pFarmManager.getUserSeedByUid(uid)
@ -253,7 +277,7 @@ diuse_farm.shortcut(
)
@diuse_farm.assign("sowing")
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1),):
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)):
if not name.available:
await MessageUtils.build_message(
"请在指令后跟需要播种的种子名称"
@ -261,7 +285,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pFarmManager.sowing(uid, name.result, num.result)
@ -279,7 +303,7 @@ diuse_farm.shortcut(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pFarmManager.harvest(uid)
@ -296,7 +320,7 @@ diuse_farm.shortcut(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pFarmManager.eradicate(uid)
@ -314,7 +338,7 @@ diuse_farm.shortcut(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pFarmManager.getUserPlantByUid(uid)
@ -331,7 +355,7 @@ reclamation = on_alconna(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
condition = await g_pFarmManager.reclamationCondition(uid)
@ -360,10 +384,10 @@ diuse_farm.shortcut(
)
@diuse_farm.assign("sell-plant")
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1),):
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
@ -380,7 +404,7 @@ diuse_farm.shortcut(
async def _(session: Uninfo, target: Match[At]):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
if not target.available:
@ -412,7 +436,7 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
result = await g_pFarmManager.buyPointByUid(uid, num.result)
@ -430,12 +454,12 @@ diuse_farm.shortcut(
async def _(session: Uninfo, name: Match[str]):
if not name.available:
await MessageUtils.build_message(
"请在指令后跟需要更改的用户"
"请在指令后跟需要更改的农场"
).finish(reply_to=True)
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
safeName = sanitize_username(name.result)
@ -443,9 +467,9 @@ async def _(session: Uninfo, name: Match[str]):
result = await g_pDBService.user.updateUserNameByUid(uid, safeName)
if result == True:
await MessageUtils.build_message("更新用户名成功!").send(reply_to=True)
await MessageUtils.build_message("更新农场名成功!").send(reply_to=True)
else:
await MessageUtils.build_message("更新用户名失败!").send(reply_to=True)
await MessageUtils.build_message("更新农场名失败!").send(reply_to=True)
diuse_farm.shortcut(
"农场签到",
@ -458,11 +482,11 @@ diuse_farm.shortcut(
async def _(session: Uninfo):
uid = str(session.user.id)
if await isRegisteredByUid(uid) == False:
if not await isRegisteredByUid(uid):
return
#判断签到是否正常加载
if g_bSignStatus == False:
if not g_bSignStatus:
await MessageUtils.build_message("签到功能异常!").send()
return
@ -475,7 +499,6 @@ async def _(session: Uninfo):
if status == 1 or status == 2:
#获取签到总天数
signDay = await g_pDBService.userSign.getUserSignCountByDate(uid, toDay.strftime("%Y-%m"))
exp, point = await g_pDBService.userSign.getUserSignRewardByDate(uid, toDay.strftime("%Y-%m-%d"))
message += f"签到成功!累计签到天数:{signDay}\n获得经验{exp},获得金币{point}"

78
config/sign_in.json Normal file
View File

@ -0,0 +1,78 @@
{
"date": "202505",
"exp_max": 50,
"exp_min": 5,
"point_max": 2000,
"point_min": 200,
"continuou":
{
"1":
{
"point": 3000,
"exp": 20
},
"3":
{
"point": 5000,
"exp": 25,
"plant":
{
"胡萝卜": 3
}
},
"5":
{
"point": 7000,
"exp": 50,
"plant":
{
"胡萝卜": 3
}
},
"7":
{
"point": 7000,
"exp": 50,
"plant":
{
"胡萝卜": 3
}
},
"10":
{
"point": 7000,
"exp": 50,
"plant":
{
"胡萝卜": 3
}
},
"15":
{
"point": 7000,
"exp": 50,
"plant":
{
"胡萝卜": 3
}
},
"20":
{
"point": 7000,
"exp": 50,
"plant":
{
"胡萝卜": 3
}
},
"25":
{
"point": 7000,
"exp": 50,
"plant":
{
"胡萝卜": 3
}
}
}
}

View File

@ -1,6 +1,8 @@
import ast
import os
import re
from contextlib import asynccontextmanager
from unittest import result
import aiosqlite
@ -87,6 +89,102 @@ class CPlantManager:
logger.warning(f"查询作物失败: {name}", e=e)
return None
@classmethod
async def getPlantPhaseByName(cls, name: str) -> list:
"""根据作物名称获取作物各个阶段
Args:
name (str): 作物名称
Returns:
list: 阶段数组
"""
try:
async with cls.m_pDB.execute(
"SELECT phase FROM plant WHERE name = ?", (name,)
) as cursor:
row = await cursor.fetchone()
if not row:
return []
phase = row[0].split(',')
seen = set()
result = []
for x in phase:
if x not in seen:
seen.add(x)
result.append(x)
return result
except Exception as e:
logger.warning(f"查询作物阶段失败: {name}", e=e)
return []
@classmethod
async def getPlantPhaseNumberByName(cls, name: str) -> int:
"""根据作物名称获取作物总阶段数
Args:
name (str): 作物名称
Returns:
int: 总阶段数
"""
try:
async with cls.m_pDB.execute(
"SELECT phase FROM plant WHERE name = ?", (name,)
) as cursor:
row = await cursor.fetchone()
if not row:
return -1
phase = row[0].split(',')
#去重
seen = set()
result = []
for x in phase:
if x not in seen:
seen.add(x)
result.append(x)
return len(result)
except Exception as e:
logger.warning(f"查询作物阶段失败: {name}", e=e)
return -1
@classmethod
async def getPlantAgainByName(cls, name: str) -> int:
"""根据作物名称获取作物再次成熟时间
Args:
name (str): 作物名称
Returns:
int: 再次成熟时间 单位:h
"""
try:
async with cls.m_pDB.execute(
"SELECT phase FROM plant WHERE name = ?", (name,)
) as cursor:
row = await cursor.fetchone()
if not row:
return -1
phase = row[0].split(',')
again = phase[-1] - phase[3] / 60 / 60
return again
except Exception as e:
logger.warning(f"查询作物阶段失败: {name}", e=e)
return -1
@classmethod
async def existsPlant(cls, name: str) -> bool:
"""判断作物是否存在

View File

@ -8,8 +8,8 @@ from zhenxun.utils._build_image import BuildImage
from ..dbService import g_pDBService
from ..json import g_pJsonManager
from .database import CSqlManager
from ..tool import g_pToolManager
from .database import CSqlManager
class CUserSignDB(CSqlManager):
@ -22,7 +22,7 @@ class CUserSignDB(CSqlManager):
"isSupplement": "TINYINT NOT NULL DEFAULT 0", #是否补签
"exp": "INT NOT NULL DEFAULT 0", #当天签到经验
"point": "INT NOT NULL DEFAULT 0", #当天签到金币
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')",#创建时间
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))",#创建时间
"PRIMARY KEY": "(uid, signDate)"
}
@ -35,7 +35,7 @@ class CUserSignDB(CSqlManager):
"lastSignDate": "DATE DEFAULT NULL", #上次签到日期
"continuousDays": "INT NOT NULL DEFAULT 0", #连续签到天数
"supplementCount": "INT NOT NULL DEFAULT 0", #补签次数
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')"#更新时间
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))"#更新时间
}
await cls.ensureTableSchema("userSignLog", userSignLog)
@ -188,7 +188,7 @@ class CUserSignDB(CSqlManager):
)
#计算累签奖励
reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays + 1}", None)
reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays}", None)
if reward:
point += reward.get('point', 0)

View File

@ -4,8 +4,8 @@ from zhenxun.services.log import logger
from ..dbService import g_pDBService
from ..json import g_pJsonManager
from .database import CSqlManager
from ..tool import g_pToolManager
from .database import CSqlManager
class CUserSoilDB(CSqlManager):
@ -241,6 +241,45 @@ class CUserSoilDB(CSqlManager):
(value, uid, soilIndex),
)
@classmethod
async def updateUserSoilFields(cls, uid: str, soilIndex: int, updates: dict) -> bool:
"""批量更新指定用户土地的多个字段
Args:
uid (str): 用户ID
soilIndex (int): 土地索引
updates (dict): 字段-新值的字典
Returns:
bool: 如果无可更新字段则返回 False否则更新成功返回 True
"""
#允许更新的列白名单
allowedFields = {
"plantName", "plantTime", "matureTime", "soilLevel",
"wiltStatus", "fertilizerStatus", "bugStatus",
"weedStatus", "waterStatus", "harvestCount"
}
setClauses = []
values = []
for field, value in updates.items():
if field not in allowedFields:
continue
setClauses.append(f'"{field}" = ?')
values.append(value)
if not setClauses:
return False
values.extend([uid, soilIndex])
sql = f'UPDATE userSoil SET {", ".join(setClauses)} WHERE uid = ? AND soilIndex = ?'
try:
async with cls._transaction():
await cls.m_pDB.execute(sql, tuple(values))
return True
except Exception as e:
logger.error(f"批量更新土地字段失败: {e}")
return False
@classmethod
async def deleteUserSoil(cls, uid: str, soilIndex: int):
"""删除指定用户的土地记录

View File

@ -289,18 +289,19 @@ class CFarmManager:
currentTime = g_pToolManager.dateTime().now()
matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime']))
phase = await g_pDBService.plant.getPlantPhaseNumberByName(soilInfo['plantName'])
#如果当前时间大于成熟时间 说明作物成熟
if currentTime >= matureTime:
phase = int(plantInfo['phase'])
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase - 1}.png")
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase}.png")
return True, plant, True
else:
#如果是多阶段作物 且没有成熟
if soilInfo['harvestCount'] >= 1:
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 2}.png")
#如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片
# if soilInfo['harvestCount'] >= 1:
# plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1s}.png")
return True, plant, False
# return True, plant, False
#如果没有成熟 则根据当前阶段进行绘制
plantedTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['plantTime']))
@ -308,7 +309,7 @@ class CFarmManager:
elapsedTime = currentTime - plantedTime
elapsedHour = elapsedTime.total_seconds() / 3600
currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1)))
currentStage = int(elapsedHour / (plantInfo['time'] / phase))
if currentStage <= 0:
if plantInfo['general'] == False:
@ -334,7 +335,6 @@ class CFarmManager:
"收获数量",
"成熟时间(小时)",
"收获次数",
"再次成熟时间(小时)",
"是否可以上架交易行"
]
@ -358,7 +358,7 @@ class CFarmManager:
iconPath = g_sResourcePath / f"plant/{seedName}/icon.png"
icon = (iconPath, 33, 33) if iconPath.exists() else ""
sellable = "可以" if plantInfo['again'] else "不可以"
sellable = "可以" if plantInfo['sell'] else "不可以"
dataList.append([
icon,
@ -368,7 +368,6 @@ class CFarmManager:
plantInfo['harvest'],
plantInfo['time'],
plantInfo['crop'],
plantInfo['again'],
sellable
])
except KeyError:
@ -509,11 +508,18 @@ class CFarmManager:
if soilInfo['harvestCount'] + 1 >= plantInfo['crop']:
await g_pDBService.userSoil.updateUserSoil(uid, i, "wiltStatus", 1)
else:
matureTs = int(currentTime.timestamp()) + int(plantInfo.get("again", 0)) * 3600
phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
await g_pDBService.userSoil.updateUserSoil(uid, i, "harvestCount", soilInfo['harvestCount'] + 1)
await g_pDBService.userSoil.updateUserSoil(uid, i, "lastResetTime", int(currentTime.timestamp()))
await g_pDBService.userSoil.updateUserSoil(uid, i, "matureTime", matureTs)
ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1
p1, p2, *rest = phase
await g_pDBService.userSoil.updateUserSoilFields(uid, i,
{
"harvestCount": hc,
"plantTime": ts - p1 - p2,
"matureTime": ts + p2 + sum(rest),
}
)
await g_pEventManager.m_afterHarvest.emit(uid=uid, name=soilInfo['plantName'], num=number, soilIndex=i)
@ -619,7 +625,7 @@ class CFarmManager:
if icon_path.exists():
icon = (icon_path, 33, 33)
if plantInfo['again'] == True:
if plantInfo['sell'] == True:
sell = "可以"
else:
sell = "不可以"
@ -722,11 +728,18 @@ class CFarmManager:
if soilInfo['harvestCount'] + 1 >= plantInfo['crop']:
await g_pDBService.userSoil.updateUserSoil(target, i, "wiltStatus", 1)
else:
matureTs = int(currentTime.timestamp()) + int(plantInfo.get("again", 0)) * 3600
phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
await g_pDBService.userSoil.updateUserSoil(uid, i, "harvestCount", soilInfo['harvestCount'] + 1)
await g_pDBService.userSoil.updateUserSoil(uid, i, "lastResetTime", int(currentTime.timestamp()))
await g_pDBService.userSoil.updateUserSoil(uid, i, "matureTime", matureTs)
ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1
p1, p2, *rest = phase
await g_pDBService.userSoil.updateUserSoilFields(uid, i,
{
"harvestCount": hc,
"plantTime": ts - p1 - p2,
"matureTime": ts + p2 + sum(rest),
}
)
await g_pDBService.userSteal.addStealRecord(target, i, uid, randomNumber, int(g_pToolManager.dateTime().now().timestamp()))

View File

@ -12,16 +12,28 @@ from ..json import g_pJsonManager
class CShopManager:
@classmethod
async def getSeedShopImage(cls, num: int = 1) -> bytes:
async def getSeedShopImage(cls, filterKey: str|int = 1, num: int = 1) -> bytes:
"""获取商店页面
Args:
filterKey (str|int):
- 字符串: 根据关键字筛选种子名称
- 整数: 翻至对应页无筛选
num (int, optional): filterKey 为字符串时用于指定页码Defaults to 1.
Returns:
bytes: 返回商店图片bytes
"""
# 解析参数:区分筛选关键字和页码
filterStr = None
if isinstance(filterKey, int):
page = filterKey
else:
filterStr = filterKey
page = num
dataList = []
# 表头定义
columnName = [
"-",
"种子名称",
@ -32,59 +44,65 @@ class CShopManager:
"收获数量",
"成熟时间(小时)",
"收获次数",
"再次成熟时间(小时)",
"是否可以上架交易行"
]
sell = ""
# 查询所有可购买作物,并根据筛选关键字过滤
plants = await g_pDBService.plant.listPlants()
plantSize = await g_pDBService.plant.countPlants(True)
start = (num - 1) * 15
items = islice(plants, start, start + 15)
for plant in items:
filteredPlants = []
for plant in plants:
# 跳过未解锁购买的种子
if plant['isBuy'] == 0:
continue
# 字符串筛选
if filterStr and filterStr not in plant['name']:
continue
filteredPlants.append(plant)
# 计算分页
totalCount = len(filteredPlants)
pageCount = math.ceil(totalCount / 15) if totalCount else 1
startIndex = (page - 1) * 15
pageItems = filteredPlants[startIndex: startIndex + 15]
# 构建数据行
dataList = []
for plant in pageItems:
# 图标处理
icon = ""
iconPath = g_sResourcePath / f"plant/{plant['name']}/icon.png"
if iconPath.exists():
icon = (iconPath, 33, 33)
if plant['again'] == True:
sell = "可以"
else:
sell = "不可以"
# 交易行标记
sell = "可以" if plant['sell'] else "不可以"
dataList.append(
[
icon,
plant['name'],
plant['buy'],
plant['level'],
plant['price'],
plant['experience'],
plant['harvest'],
plant['time'],
plant['crop'],
plant['again'],
sell
]
)
dataList.append([
icon,
plant['name'], # 种子名称
plant['buy'], # 种子单价
plant['level'], # 解锁等级
plant['price'], # 果实单价
plant['experience'], # 收获经验
plant['harvest'], # 收获数量
plant['time'], # 成熟时间(小时)
plant['crop'], # 收获次数
sell # 是否可上架交易行
])
count = math.ceil(plantSize / 15)
title = f"种子商店 页数: {num}/{count}"
# 页码标题
title = f"种子商店 页数: {page}/{pageCount}"
# 渲染表格并返回图片bytes
result = await ImageTemplate.table_page(
title,
"购买示例:@小真寻 购买种子 大白菜 5",
columnName,
dataList,
)
return result.pic2bytes()
@classmethod
async def buySeed(cls, uid: str, name: str, num: int = 1) -> str:
"""购买种子
@ -120,7 +138,7 @@ class CShopManager:
else:
await g_pDBService.user.updateUserPointByUid(uid, point - total)
if await g_pDBService.userSeed.addUserSeedByUid(uid, name, num) == False:
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
return "购买失败,执行数据库错误!"
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"

View File

@ -1,5 +1,19 @@
# 真寻农场更新日志
## V1.4
用户方面
---
- 新增种子商店筛选功能如果没有BUG的话后续我的种子、我的作物等也会加入筛选功能
- 新增签到功能(测试
- 新增农场详述功能,能通过该功能更加详细的观看农场数据
- 修复了迁移旧数据库无法正常迁移的BUG
代码方面
---
- 修正了多阶段作物成长素材计算逻辑
- 修正了作物数据库字段错乱的问题
- 作物新增offset字段用于以后偏移坐标尚未加入代码 TODO
## V1.3
用户方面
---

Binary file not shown.