This commit is contained in:
qsc
2026-06-19 18:12:30 +08:00
parent 62917a0dbc
commit 104772ba2e
21 changed files with 2967 additions and 28 deletions
+4
View File
@@ -1,5 +1,9 @@
## 更新记录
### version: 2.4
增加大量新指令
### version: 2.3
宏查询接口调整,恢复使用
+806 -1
View File
@@ -11,6 +11,29 @@ from .request import APIClient
from .sqlite import AsyncSQLiteDB
from .fun_basic import load_template,gold_to_string,week_to_num,compare_date_str
ROLE_RANK_NAMES = {
"名士五十强",
"老江湖五十强",
"兵甲藏家五十强",
"名师五十强",
"阵营英雄五十强",
"薪火相传五十强",
"庐园广记一百强",
}
TONG_RANK_NAMES = {
"浩气神兵宝甲五十强",
"恶人神兵宝甲五十强",
"浩气爱心帮会五十强",
"恶人爱心帮会五十强",
"赛季恶人五十强",
"赛季浩气五十强",
"上周恶人五十强",
"上周浩气五十强",
"本周恶人五十强",
"本周浩气五十强",
}
class JX3Service:
def __init__(self, api_data_path: str, config: AstrBotConfig, sqlite: AsyncSQLiteDB):
# 加载API配置文件
@@ -701,6 +724,253 @@ class JX3Service:
return return_data
async def zhenyan(self, name: str) -> Dict[str, Any]:
"""阵眼"""
return_data = self._init_return_data()
# 1. 构造请求参数
params = {"name": name, "ticket": self.ticket, "token": self.token}
# 2. 调用基础请求
data: Optional[Dict[str, Any]] = await self._base_request(
"jx3_zhenyan", "GET", params=params
)
if not data or not isinstance(data, dict):
return_data["msg"] = "未查询到该心法阵眼信息"
return return_data
# 3. 处理返回数据
try:
items = data.get("data", [])
if not isinstance(items, list) or not items:
return_data["msg"] = "未查询到该心法阵眼信息"
return return_data
result_msg = f"{data.get('name', name)}-{data.get('skillName', '')}\n"
for item in items:
if not isinstance(item, dict):
continue
result_msg += f"{item.get('name', '')}{item.get('desc', '')}\n"
return_data["data"] = result_msg.rstrip()
except Exception as e:
logger.error(f"处理阵眼数据失败: {e}")
return_data["msg"] = "处理阵眼数据失败"
return return_data
return_data["code"] = 200
return return_data
async def qixue(self, name: str) -> Dict[str, Any]:
"""奇穴"""
return_data = self._init_return_data()
# 1. 构造请求参数
params = {"name": name, "ticket": self.ticket, "token": self.token}
# 2. 调用基础请求
data: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_qixue", "GET", params=params
)
if not data or not isinstance(data, list):
return_data["msg"] = "未查询到该心法奇穴信息"
return return_data
# 3. 处理返回数据
try:
level_titles = {
1: "主奇穴",
2: "第一重",
3: "第二重",
4: "第三重",
5: "第四重",
6: "第五重",
7: "第六重",
8: "混池",
}
groups = []
for group in data:
if not isinstance(group, dict):
continue
level = group.get("level")
try:
level_key = int(level)
except (TypeError, ValueError):
level_key = 0
items = group.get("data", [])
if not isinstance(items, list) or not items:
continue
parsed_items = []
for item in items:
if not isinstance(item, dict):
continue
class_value = item.get("class")
is_active = class_value == 1 or str(class_value) == "1"
parsed_items.append({
"name": item.get("name", ""),
"icon": item.get("icon", ""),
"desc": item.get("desc", ""),
"class_text": "主动" if is_active else "被动",
"interval": item.get("interval", "") if is_active else "",
})
if parsed_items:
groups.append({
"level": level_key,
"title": level_titles.get(level_key, f"{level_key}"),
"talents": parsed_items,
})
if not groups:
return_data["msg"] = "未查询到该心法奇穴信息"
return return_data
groups.sort(key=lambda item: item["level"])
return_data["data"] = {
"name": name,
"groups": groups,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"处理奇穴数据失败: {e}")
return_data["msg"] = "处理奇穴数据失败"
return return_data
# 4. 加载模板
try:
return_data["temp"] = await load_template("qixue.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def jineng(self, name: str) -> Dict[str, Any]:
"""技能"""
return_data = self._init_return_data()
params = {"name": name, "ticket": self.ticket, "token": self.token}
data: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_jineng", "GET", params=params
)
if not data or not isinstance(data, list):
return_data["msg"] = "未查询到该心法技能信息"
return return_data
try:
groups = []
for group in data:
if not isinstance(group, dict):
continue
skills = group.get("data", [])
if not isinstance(skills, list) or not skills:
continue
parsed_skills = []
for skill in skills:
if not isinstance(skill, dict):
continue
parsed_skills.append({
"name": skill.get("name", ""),
"icon": skill.get("icon", ""),
"desc": skill.get("desc", ""),
"interval": skill.get("interval", ""),
"distance": skill.get("distance", ""),
"release_type": skill.get("releaseType", ""),
"weapon": skill.get("weapon", ""),
})
if parsed_skills:
groups.append({
"title": group.get("class", "其他技能"),
"skills": parsed_skills,
})
if not groups:
return_data["msg"] = "未查询到该心法技能信息"
return return_data
return_data["data"] = {
"name": name,
"groups": groups,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"处理技能数据失败: {e}")
return_data["msg"] = "处理技能数据失败"
return return_data
try:
return_data["temp"] = await load_template("jineng.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def zilipaixing(self, school: str, server: str) -> Dict[str, Any]:
"""资历排行"""
return_data = self._init_return_data()
params = {
"server": server,
"school": school,
"ticket": self.ticket,
"token": self.token,
}
data: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_zilipaixing", "GET", params=params
)
if not data or not isinstance(data, list):
return_data["msg"] = "未查询到资历排行信息"
return return_data
try:
return_data["data"] = {
"items": data,
"school": school,
"server": server,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"处理资历排行数据失败: {e}")
return_data["msg"] = "处理资历排行数据失败"
return return_data
try:
return_data["temp"] = await load_template("zilipaixing.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def shaohua(self) -> Dict[str, Any]:
"""骚话"""
return_data = self._init_return_data()
@@ -1051,6 +1321,74 @@ class JX3Service:
return return_data
async def weizuoqiyu(self, name: str, server: str) -> Dict[str, Any]:
"""未做奇遇"""
return_data = self._init_return_data()
# 1. 构造请求参数
params = {"server": server, "name": name, "token": self.token}
# 2. 调用基础请求
data: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_weizuoqiyu", "GET", params=params
)
if not data:
return_data["msg"] = "未查询到未做奇遇信息"
return return_data
if not isinstance(data, list):
return_data["msg"] = "获取接口信息失败或数据格式错误"
return return_data
# 3. 处理返回数据
try:
return_data["data"]["ptqy"] = []
return_data["data"]["jsqy"] = []
return_data["data"]["name"] = name
return_data["data"]["server"] = server
for item in data:
event_name = item.get("name") or item.get("event")
if not event_name:
continue
try:
level = int(item.get("level", 0))
except (TypeError, ValueError):
continue
event_item = {
"event": event_name,
"time": "未触发"
}
if level == 1:
return_data["data"]["ptqy"].append(event_item)
elif level == 2:
return_data["data"]["jsqy"].append(event_item)
if not return_data["data"]["ptqy"] and not return_data["data"]["jsqy"]:
return_data["msg"] = "未查询到未做普通或绝世奇遇"
return return_data
except Exception as e:
logger.error(f"处理返回数据失败: {e}")
return_data["msg"] = "处理返回数据失败"
return return_data
# 4. 加载模板
try:
return_data["temp"] = await load_template("weizuoqiyu.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def qiyutongji(self, name: str, server: str) -> Dict[str, Any]:
"""奇遇统计"""
return_data = self._init_return_data()
@@ -1100,6 +1438,131 @@ class JX3Service:
return return_data
async def jinqiqiyu(self, server: str) -> Dict[str, Any]:
"""近期奇遇"""
return_data = self._init_return_data()
params = {"server": server, "token": self.token}
data_list: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_jinqiqiyu", "GET", params=params
)
if not data_list or not isinstance(data_list, list):
return_data["msg"] = "未查询到近期奇遇信息"
return return_data
# 格式化时间
try:
for item in data_list:
event_time = item.get("time")
if event_time:
try:
item["time"] = datetime.fromtimestamp(int(event_time)).strftime("%Y-%m-%d %H:%M:%S")
except (TypeError, ValueError, OSError):
item["time"] = str(event_time)
else:
item["time"] = ""
except Exception as e:
logger.error(f"数据处理时出错: {e}")
return_data["msg"] = "处理接口返回信息时出错"
return return_data
# 准备模板渲染数据
try:
return_data["data"] = {
"items": data_list,
"server": server,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"模板数据准备失败: {e}")
return_data["msg"] = "系统错误:模板渲染数据准备失败"
return return_data
# 加载模板
try:
return_data["temp"] = await load_template("jinqiqiyu.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def qiyuhuizong(self, server: str, num: int = 7) -> Dict[str, Any]:
"""奇遇汇总"""
return_data = self._init_return_data()
if num < 1 or num > 30:
return_data["msg"] = "汇总天数需在 1-30 天之间"
return return_data
params = {"server": server, "num": num, "token": self.token}
data_list: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_qiyuhuizong", "GET", params=params
)
if not data_list or not isinstance(data_list, list):
return_data["msg"] = "未查询到奇遇汇总信息"
return return_data
# 整理最近一次触发信息
try:
for item in data_list:
latest = item.get("data")
if not isinstance(latest, dict):
latest = {}
item["latest_name"] = latest.get("name", "")
latest_time = latest.get("time")
if latest_time:
try:
item["latest_time"] = datetime.fromtimestamp(int(latest_time)).strftime("%Y-%m-%d %H:%M:%S")
except (TypeError, ValueError, OSError):
item["latest_time"] = str(latest_time)
else:
item["latest_time"] = ""
except Exception as e:
logger.error(f"数据处理时出错: {e}")
return_data["msg"] = "处理接口返回信息时出错"
return return_data
# 准备模板渲染数据
try:
return_data["data"] = {
"items": data_list,
"server": server,
"num": num,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"模板数据准备失败: {e}")
return_data["msg"] = "系统错误:模板渲染数据准备失败"
return return_data
# 加载模板
try:
return_data["temp"] = await load_template("qiyuhuizong.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def zhanji(self, name: str, server:str, mode:str) -> Dict[str, Any]:
"""战绩"""
return_data = self._init_return_data()
@@ -1162,6 +1625,52 @@ class JX3Service:
return return_data
async def mingjiantongji(self, mode: str = "33") -> Dict[str, Any]:
"""名剑统计"""
return_data = self._init_return_data()
mode = str(mode)
if mode not in {"22", "33", "55"}:
return_data["msg"] = "模式错误,可选值:22、33、55"
return return_data
# 1. 构造请求参数
params = {"mode": mode, "token": self.token, "ticket": self.ticket}
# 2. 调用基础请求
data: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_mingjiantongji", "GET", params=params
)
if not data or not isinstance(data, list):
return_data["msg"] = "未查询到名剑统计信息"
return return_data
# 3. 准备模板渲染数据
try:
return_data["data"] = {
"items": data,
"mode": mode,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"模板数据准备失败: {e}")
return_data["msg"] = "系统错误:模板渲染数据准备失败"
return return_data
# 4. 加载模板
try:
return_data["temp"] = await load_template("mingjiantongji.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def tuanduizhaomu(self, server: str, keyword: str) -> Dict[str, Any]:
"""团队招募"""
return_data = self._init_return_data()
@@ -1202,6 +1711,115 @@ class JX3Service:
return return_data
async def shitu(self, type_value: int, keyword: str, server: str) -> Dict[str, Any]:
"""师徒招募"""
return_data = self._init_return_data()
if type_value not in {1, 2}:
return_data["msg"] = "师徒查询类型错误"
return return_data
# 1. 构造请求参数
params = {"type": type_value, "server": server, "keyword": keyword, "token": self.token}
# 2. 调用基础请求
data: Optional[Dict[str, Any]] = await self._base_request(
"jx3_shitu", "GET", params=params
)
if not data or not isinstance(data, dict):
return_data["msg"] = "未查询到师徒招募信息"
return return_data
# 3. 处理返回数据
try:
items = data.get("data", [])
if not items:
return_data["msg"] = "未查询到师徒招募信息"
return return_data
title = "收徒信息" if type_value == 1 else "拜师信息"
return_data["data"] = {
"items": items,
"server": data.get("server", server),
"keyword": keyword,
"type_value": type_value,
"title": title,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"数据处理时出错: {e}")
return_data["msg"] = "处理接口返回信息时出错"
return return_data
# 4. 加载模板
try:
return_data["temp"] = await load_template("shitu.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def rank_statistical(self, name: str, server: str) -> Dict[str, Any]:
"""各类风云录榜单"""
return_data = self._init_return_data()
if name in ROLE_RANK_NAMES:
template_name = "rank_role.html"
elif name in TONG_RANK_NAMES:
template_name = "rank_tong.html"
else:
return_data["msg"] = "榜单名称错误"
return return_data
# 1. 构造请求参数
params = {"server": server, "name": name, "token": self.token}
# 2. 调用基础请求
data: Optional[Dict[str, Any]] = await self._base_request(
"jx3_rank_statistical", "GET", params=params
)
if not data or not isinstance(data, dict):
return_data["msg"] = "未查询到榜单信息"
return return_data
# 3. 处理返回数据
try:
items = data.get("data", [])
if not isinstance(items, list) or not items:
return_data["msg"] = "未查询到榜单信息"
return return_data
return_data["data"] = {
"items": items,
"server": data.get("server", server),
"rank_name": data.get("name", name),
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"数据处理时出错: {e}")
return_data["msg"] = "处理接口返回信息时出错"
return return_data
# 4. 加载模板
try:
return_data["temp"] = await load_template(template_name)
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def jueshe(self,name: str, server: str) -> Dict[str, Any]:
"""角色"""
return_data = self._init_return_data()
@@ -1243,7 +1861,129 @@ class JX3Service:
async def jueshemingpian(self, server: str, name: str) -> Dict[str, Any]:
"""角色名片"""
"""单张名片"""
return_data = self._init_return_data()
# 1. 构造请求参数
params = {"server": server, "name": name, "token": self.token}
# 2. 调用基础请求
data: Optional[Dict[str, Any]] = await self._base_request(
"jx3_jieshemingpian", "GET", params=params
)
if not data or not isinstance(data, dict):
return_data["msg"] = "未找到该角色名片"
return return_data
# 3. 处理返回数据
try:
url = data.get("showAvatar")
if not url:
return_data["msg"] = "未获取到名片图片"
return return_data
server_name = data.get("serverName", server)
role_name = data.get("roleName", name)
show_like = data.get("showLike", 0)
msg = f"{server_name}-{role_name} 点赞:{show_like}"
return_data["data"] = [
Comp.Plain(msg),
Comp.Image.fromURL(url),
]
except Exception as e:
logger.error(f"数据处理时出错: {e}")
return_data["msg"] = "处理接口返回信息时出错"
return return_data
return_data["code"] = 200
return return_data
async def jingnai(self, name: str, server: str) -> Dict[str, Any]:
"""百战精耐"""
return_data = self._init_return_data()
# 1. 构造请求参数
params = {"server": server, "name": name, "token": self.token}
# 2. 调用基础请求
data: Optional[Dict[str, Any]] = await self._base_request(
"jx3_jingnai", "GET", params=params
)
if not data or not isinstance(data, dict):
return_data["msg"] = "未查询到角色精耐信息"
return return_data
# 3. 处理返回数据
try:
items = data.get("skill_list", [])
if not isinstance(items, list) or not items:
return_data["msg"] = "未查询到技能信息"
return return_data
color_map = {
7: "黑色",
6: "紫色",
5: "红色",
4: "绿色",
3: "蓝色",
2: "黄色",
0: "",
}
for item in items:
if not isinstance(item, dict):
continue
color = item.get("skill_color")
try:
color_key = int(color)
except (TypeError, ValueError):
color_key = None
item["skill_color_text"] = color_map.get(color_key, str(color) if color is not None else "")
update_time = data.get("update_time")
if update_time:
try:
update_time = datetime.fromtimestamp(int(update_time)).strftime("%Y-%m-%d %H:%M:%S")
except (TypeError, ValueError, OSError):
update_time = str(update_time)
else:
update_time = ""
return_data["data"] = {
"server": data.get("server", server),
"role_name": data.get("role_name", name),
"skill_energy": data.get("skill_energy", ""),
"skill_stamina": data.get("skill_stamina", ""),
"skill_count": data.get("skill_count", len(items)),
"items": items,
"update_time": update_time
}
except Exception as e:
logger.error(f"处理精耐数据失败: {e}")
return_data["msg"] = "处理精耐数据失败"
return return_data
# 4. 加载模板
try:
return_data["temp"] = await load_template("jingnai.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return_data["code"] = 200
return return_data
async def shuoyoumingpian(self, server: str, name: str) -> Dict[str, Any]:
"""所有名片"""
return_data = self._init_return_data()
# 1. 构造请求参数
@@ -1492,6 +2232,71 @@ class JX3Service:
return return_data
return return_data
async def diaoluo(self, name: str, limit: int = 20, server: str = "") -> Dict[str, Any]:
"""物品掉落记录"""
return_data = self._init_return_data()
try:
limit = int(limit)
except (TypeError, ValueError):
return_data["msg"] = "数量必须是数字"
return return_data
if limit < 1 or limit > 100:
return_data["msg"] = "掉落记录数量需在 1-100 之间"
return return_data
# 1. 构造请求参数
params = {"server": server, "name": name, "limit": limit, "token": self.token}
# 2. 调用基础请求
data: Optional[List[Dict[str, Any]]] = await self._base_request(
"jx3_diaoluo", "GET", params=params
)
if not data or not isinstance(data, list):
return_data["msg"] = "未查询到掉落记录"
return return_data
# 3. 处理返回数据
try:
for item in data:
if not isinstance(item, dict):
continue
drop_time = item.get("time")
if drop_time:
try:
item["time"] = datetime.fromtimestamp(int(drop_time)).strftime("%Y-%m-%d %H:%M:%S")
except (TypeError, ValueError, OSError):
item["time"] = str(drop_time)
else:
item["time"] = ""
return_data["data"] = {
"items": data,
"name": name,
"limit": limit,
"server": server,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
logger.error(f"处理掉落数据失败: {e}")
return_data["msg"] = "处理掉落数据失败"
return return_data
# 4. 模板渲染
try:
return_data["temp"] = await load_template("diaoluo.html")
return_data["code"] = 200
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return return_data
return return_data
async def bagua(self, type: str) -> Dict[str, Any]:
+172 -1
View File
@@ -262,6 +262,26 @@ class MessageBuilder:
return await self.T2I_image_msg(event, self.jx3api.xiaoyao)
async def jx3_zhenyan(self, event: AstrMessageEvent, name: str):
"""剑三 阵眼 心法"""
return await self.plain_msg(event, lambda: self.jx3api.zhenyan(name))
async def jx3_qixue(self, event: AstrMessageEvent, name: str):
"""剑三 奇穴 心法"""
return await self.T2I_image_msg(event, lambda: self.jx3api.qixue(name))
async def jx3_jineng(self, event: AstrMessageEvent, name: str):
"""剑三 技能 心法"""
return await self.T2I_image_msg(event, lambda: self.jx3api.jineng(name))
async def jx3_zilipaixing(self, event: AstrMessageEvent, school: str, server: str = ""):
"""剑三 资历排行 职业 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.zilipaixing(school, self.serverdefault(server)))
async def jx3_shaohua(self, event: AstrMessageEvent,):
"""剑三 骚话"""
return await self.plain_msg(event, self.jx3api.shaohua)
@@ -307,11 +327,34 @@ class MessageBuilder:
return await self.T2I_image_msg(event, lambda: self.jx3api.juesheqiyu(name, self.serverdefault(server)))
async def jx3_weizuoqiyu(self, event: AstrMessageEvent,name: str = "飞翔大野猪", server: str = ""):
"""剑三 未做奇遇 角色名称 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.weizuoqiyu(name, self.serverdefault(server)))
async def jx3_qiyutongji(self, event: AstrMessageEvent,adventureName: str = "阴阳两界", server: str = ""):
"""剑三 奇遇统计 奇遇名称 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.qiyutongji(adventureName,self.serverdefault(server)))
async def jx3_jinqiqiyu(self, event: AstrMessageEvent,server: str = ""):
"""剑三 近期奇遇 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.jinqiqiyu(self.serverdefault(server)))
async def jx3_qiyuhuizong(self, event: AstrMessageEvent,num_or_server: str = "7", server: str = ""):
"""剑三 奇遇汇总 天数 服务器"""
num = 7
target_server = server
if str(num_or_server).isdigit():
num = int(num_or_server)
else:
target_server = num_or_server
return await self.T2I_image_msg(event, lambda: self.jx3api.qiyuhuizong(self.serverdefault(target_server), num))
async def jx3_zhanji(self, event: AstrMessageEvent,name: str = "飞翔大野猪", server: str = "", mode:str = "33"):
"""剑三 战绩 角色 服务器 类型"""
return await self.T2I_image_msg(event, lambda: self.jx3api.zhanji(name, self.serverdefault(server),mode))
@@ -322,11 +365,116 @@ class MessageBuilder:
return await self.T2I_image_msg(event, lambda: self.jx3api.mingjianpaihang(limit,mode))
async def jx3_mingjiantongji(self, event: AstrMessageEvent,mode: str = "33"):
"""剑三 名剑统计 模式"""
return await self.T2I_image_msg(event, lambda: self.jx3api.mingjiantongji(mode))
async def jx3_tuanduizhaomu(self, event: AstrMessageEvent,keyword: str = "25人普通会战弓月城", server: str = ""):
"""剑三 招募 副本 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.tuanduizhaomu( self.serverdefault(server),keyword))
async def jx3_baishi(self, event: AstrMessageEvent,keyword: str = "", server: str = ""):
"""剑三 拜师 搜索关键词 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.shitu(2, keyword, self.serverdefault(server)))
async def jx3_shoutu(self, event: AstrMessageEvent,keyword: str = "", server: str = ""):
"""剑三 收徒 搜索关键词 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.shitu(1, keyword, self.serverdefault(server)))
async def jx3_rank_statistical(self, event: AstrMessageEvent, rank_name: str, server: str = ""):
"""剑三 各类榜单 榜单名称 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.rank_statistical(rank_name, self.serverdefault(server)))
async def jx3_mingshiwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 名士五十强 服务器"""
return await self.jx3_rank_statistical(event, "名士五十强", server)
async def jx3_laojianghuwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 老江湖五十强 服务器"""
return await self.jx3_rank_statistical(event, "老江湖五十强", server)
async def jx3_bingjiacangjiawushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 兵甲藏家五十强 服务器"""
return await self.jx3_rank_statistical(event, "兵甲藏家五十强", server)
async def jx3_mingshiwushiqiang_mentor(self, event: AstrMessageEvent, server: str = ""):
"""剑三 名师五十强 服务器"""
return await self.jx3_rank_statistical(event, "名师五十强", server)
async def jx3_zhengyingyingxiongwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 阵营英雄五十强 服务器"""
return await self.jx3_rank_statistical(event, "阵营英雄五十强", server)
async def jx3_xinhuoxiangchuanwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 薪火相传五十强 服务器"""
return await self.jx3_rank_statistical(event, "薪火相传五十强", server)
async def jx3_luyuanguangjiyibaiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 庐园广记一百强 服务器"""
return await self.jx3_rank_statistical(event, "庐园广记一百强", server)
async def jx3_haoqishenbingbaojiawushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 浩气神兵宝甲五十强 服务器"""
return await self.jx3_rank_statistical(event, "浩气神兵宝甲五十强", server)
async def jx3_erenshenbingbaojiawushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 恶人神兵宝甲五十强 服务器"""
return await self.jx3_rank_statistical(event, "恶人神兵宝甲五十强", server)
async def jx3_haoqiaixinbanghuiwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 浩气爱心帮会五十强 服务器"""
return await self.jx3_rank_statistical(event, "浩气爱心帮会五十强", server)
async def jx3_erenaixinbanghuiwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 恶人爱心帮会五十强 服务器"""
return await self.jx3_rank_statistical(event, "恶人爱心帮会五十强", server)
async def jx3_saijierenwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 赛季恶人五十强 服务器"""
return await self.jx3_rank_statistical(event, "赛季恶人五十强", server)
async def jx3_saijihaoqiwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 赛季浩气五十强 服务器"""
return await self.jx3_rank_statistical(event, "赛季浩气五十强", server)
async def jx3_shangzhouerenwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 上周恶人五十强 服务器"""
return await self.jx3_rank_statistical(event, "上周恶人五十强", server)
async def jx3_shangzhouhaoqiwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 上周浩气五十强 服务器"""
return await self.jx3_rank_statistical(event, "上周浩气五十强", server)
async def jx3_benzhouerenwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 本周恶人五十强 服务器"""
return await self.jx3_rank_statistical(event, "本周恶人五十强", server)
async def jx3_benzhouhaoqiwushiqiang(self, event: AstrMessageEvent, server: str = ""):
"""剑三 本周浩气五十强 服务器"""
return await self.jx3_rank_statistical(event, "本周浩气五十强", server)
async def jx3_jueshe(self, event: AstrMessageEvent,name: str, server: str = ""):
"""剑三 角色 名称 服务器"""
return await self.plain_msg(event, lambda: self.jx3api.jueshe(name, self.serverdefault(server)))
@@ -334,7 +482,17 @@ class MessageBuilder:
async def jx3_jueshemingpian(self, event: AstrMessageEvent, name: str = "飞翔大野猪", server: str = ""):
"""剑三 名片 角色 服务器"""
return await self.plain_chain(event, lambda: self.jx3api.jueshemingpian( self.serverdefault(server),name))
return await self.plain_chain(event, lambda: self.jx3api.jueshemingpian(self.serverdefault(server), name))
async def jx3_jingnai(self, event: AstrMessageEvent, name: str = "飞翔大野猪", server: str = ""):
"""剑三 精耐 角色 服务器"""
return await self.T2I_image_msg(event, lambda: self.jx3api.jingnai(name, self.serverdefault(server)))
async def jx3_shuoyoumingpian(self, event: AstrMessageEvent, name: str = "飞翔大野猪", server: str = ""):
"""剑三 所有名片 角色 服务器"""
return await self.plain_chain(event, lambda: self.jx3api.shuoyoumingpian( self.serverdefault(server),name))
async def jx3_shuijimingpian(self, event: AstrMessageEvent,force: str = "万花", body: str = "萝莉", server: str = ""):
@@ -362,6 +520,19 @@ class MessageBuilder:
return await self.T2I_image_msg(event, lambda: self.jx3api.jiaoyihang(Name, self.serverdefault(server)))
async def jx3_diaoluo(self, event: AstrMessageEvent, name: str = "玄晶", limit_or_server: str = "20", server: str = ""):
"""剑三 掉落 物品名称 数量 服务器"""
limit = 20
target_server = server
if str(limit_or_server).isdigit():
limit = int(limit_or_server)
else:
target_server = limit_or_server
return await self.T2I_image_msg(event, lambda: self.jx3api.diaoluo(name, limit, self.serverdefault(target_server)))
async def jx3_bagua(self, event: AstrMessageEvent,name: str = "818"):
"""剑三 八卦 类型"""
return await self.plain_msg(event, lambda: self.jx3api.bagua(name))
+123 -1
View File
@@ -106,6 +106,47 @@
"params":{
}
},
"jx3_zhenyan":{
"url":"https://www.jx3api.com/data/school/matrix",
"method":"GET",
"description":"查询指定心法的阵眼效果",
"params":{
"name": "易筋经",
"ticket": "",
"token":""
}
},
"jx3_qixue":{
"url":"https://www.jx3api.com/data/school/talent",
"method":"GET",
"description":"查询指定心法的奇穴详细效果",
"params":{
"name": "易筋经",
"ticket": "",
"token":""
}
},
"jx3_jineng":{
"url":"https://www.jx3api.com/data/school/skills",
"method":"GET",
"description":"查询指定心法的技能详情",
"params":{
"name": "易筋经",
"ticket": "",
"token":""
}
},
"jx3_zilipaixing":{
"url":"https://www.jx3api.com/data/school/seniority",
"method":"GET",
"description":"查询指定门派的资历排行榜",
"params":{
"server": "梦江南",
"school": "万花",
"ticket": "",
"token":""
}
},
"jx3_shaohua":{
"url":"https://www.jx3api.com/data/saohua/random",
"method":"GET",
@@ -188,6 +229,16 @@
"token":""
}
},
"jx3_weizuoqiyu":{
"url":"https://www.jx3api.com/data/event/unfinished",
"method":"GET",
"description":"此接口用于查询指定角色未做奇遇记录,数据可能存在遗漏",
"params":{
"server": "梦江南",
"name": "飞翔大野猪",
"token":""
}
},
"jx3_qiyutongji":{
"url":"https://www.jx3api.com/data/event/statistics",
"method":"POST",
@@ -199,6 +250,25 @@
"token": ""
}
},
"jx3_jinqiqiyu":{
"url":"https://www.jx3api.com/data/event/recent",
"method":"GET",
"description":"查询指定服务器最近触发的奇遇记录列表",
"params":{
"server": "梦江南",
"token": ""
}
},
"jx3_qiyuhuizong":{
"url":"https://www.jx3api.com/data/event/collect",
"method":"GET",
"description":"统计指定服务器最近一段时间内各类奇遇触发汇总",
"params":{
"server": "梦江南",
"num": 7,
"token": ""
}
},
"jx3_zhanji":{
"url":"https://www.jx3api.com/data/arena/recent",
"method":"GET",
@@ -222,6 +292,16 @@
"token":""
}
},
"jx3_mingjiantongji":{
"url":"https://www.jx3api.com/data/arena/schools",
"method":"GET",
"description":"统计全服名剑大会各门派当前赛季与上赛季数量",
"params":{
"mode": "33",
"ticket": "",
"token":""
}
},
"jx3_tuanduizhaomu":{
"url":"https://www.jx3api.com/data/recruit/search",
"method":"GET",
@@ -233,6 +313,27 @@
"token":""
}
},
"jx3_shitu":{
"url":"https://www.jx3api.com/data/mentor/search",
"method":"GET",
"description":"查询游戏内师徒系统拜师/收徒招募信息",
"params":{
"type": 2,
"server": "梦江南",
"keyword": "",
"token":""
}
},
"jx3_rank_statistical":{
"url":"https://www.jx3api.com/data/rank/statistics",
"method":"GET",
"description":"查询全服或指定服务器的各类游戏内榜单数据",
"params":{
"server": "梦江南",
"name": "名士五十强",
"token":""
}
},
"jx3_jueshexinxi":{
"url":"https://www.jx3api.com/data/role/detail",
"method":"GET",
@@ -253,6 +354,16 @@
"token":""
}
},
"jx3_jingnai":{
"url":"https://www.jx3api.com/data/role/monster",
"method":"GET",
"description":"查询指定角色在百战异闻录玩法中的精力、耐力数值和已习得技能列表",
"params":{
"server": "梦江南",
"name": "飞翔大野猪",
"token":""
}
},
"jx3_allmingpian":{
"url":"https://www.jx3api.com/data/card/records",
"method":"GET",
@@ -313,6 +424,17 @@
"token": ""
}
},
"jx3_diaoluo":{
"url":"https://www.jx3api.com/data/reward/statistics",
"method":"GET",
"description":"统计全服或指定服务器中特定贵重物品在团队秘境中的掉落记录",
"params":{
"server": "梦江南",
"name": "玄晶",
"limit": 20,
"token": ""
}
},
"jx3_shuama":{
"url":"https://www.jx3api.com/data/ranch/records",
"method":"GET",
@@ -385,4 +507,4 @@
}
}
}
+33 -3
View File
@@ -200,6 +200,10 @@ class Jx3ApiPlugin(Star):
"状态": self.jx3cmd.jx3_zhuangtai,
"技改": self.jx3cmd.jx3_jigai,
"小药": self.jx3cmd.jx3_xiaoyao,
"阵眼": self.jx3cmd.jx3_zhenyan,
"奇穴": self.jx3cmd.jx3_qixue,
"技能": self.jx3cmd.jx3_jineng,
"资历排行": self.jx3cmd.jx3_zilipaixing,
"骚话": self.jx3cmd.jx3_shaohua,
"沙盘": self.jx3cmd.jx3_shapan,
"攻略": self.jx3cmd.jx3_qiyugonglue,
@@ -211,19 +215,45 @@ class Jx3ApiPlugin(Star):
"的卢": self.jx3cmd.jx3_dilujilu,
"烟花": self.jx3cmd.jx3_yanhuachaxun,
"骗子": self.jx3cmd.jx3_pianzhi,
"查询": self.jx3cmd.jx3_juesheqiyu,
"统计": self.jx3cmd.jx3_qiyutongji,
"奇遇": self.jx3cmd.jx3_juesheqiyu,
"未做奇遇": self.jx3cmd.jx3_weizuoqiyu,
"奇遇统计": self.jx3cmd.jx3_qiyutongji,
"近期奇遇": self.jx3cmd.jx3_jinqiqiyu,
"奇遇汇总": self.jx3cmd.jx3_qiyuhuizong,
"战绩": self.jx3cmd.jx3_zhanji,
"排行": self.jx3cmd.jx3_mingjianpaihang,
"名剑统计": self.jx3cmd.jx3_mingjiantongji,
"招募": self.jx3cmd.jx3_tuanduizhaomu,
"拜师": self.jx3cmd.jx3_baishi,
"收徒": self.jx3cmd.jx3_shoutu,
"名士五十强": self.jx3cmd.jx3_mingshiwushiqiang,
"老江湖五十强": self.jx3cmd.jx3_laojianghuwushiqiang,
"兵甲藏家五十强": self.jx3cmd.jx3_bingjiacangjiawushiqiang,
"名师五十强": self.jx3cmd.jx3_mingshiwushiqiang_mentor,
"阵营英雄五十强": self.jx3cmd.jx3_zhengyingyingxiongwushiqiang,
"薪火相传五十强": self.jx3cmd.jx3_xinhuoxiangchuanwushiqiang,
"庐园广记一百强": self.jx3cmd.jx3_luyuanguangjiyibaiqiang,
"浩气神兵宝甲五十强": self.jx3cmd.jx3_haoqishenbingbaojiawushiqiang,
"恶人神兵宝甲五十强": self.jx3cmd.jx3_erenshenbingbaojiawushiqiang,
"浩气爱心帮会五十强": self.jx3cmd.jx3_haoqiaixinbanghuiwushiqiang,
"恶人爱心帮会五十强": self.jx3cmd.jx3_erenaixinbanghuiwushiqiang,
"赛季恶人五十强": self.jx3cmd.jx3_saijierenwushiqiang,
"赛季浩气五十强": self.jx3cmd.jx3_saijihaoqiwushiqiang,
"上周恶人五十强": self.jx3cmd.jx3_shangzhouerenwushiqiang,
"上周浩气五十强": self.jx3cmd.jx3_shangzhouhaoqiwushiqiang,
"本周恶人五十强": self.jx3cmd.jx3_benzhouerenwushiqiang,
"本周浩气五十强": self.jx3cmd.jx3_benzhouhaoqiwushiqiang,
"角色": self.jx3cmd.jx3_jueshe,
"名片": self.jx3cmd.jx3_jueshemingpian,
"随机": self.jx3cmd.jx3_shuijimingpian,
"精耐": self.jx3cmd.jx3_jingnai,
"所有名片": self.jx3cmd.jx3_shuoyoumingpian,
"随机名片": self.jx3cmd.jx3_shuijimingpian,
"刷马": self.jx3cmd.jx3_shuma,
"金价": self.jx3cmd.jx3_jinjia,
"物价": self.jx3cmd.jx3_wujia,
"八卦": self.jx3cmd.jx3_bagua,
"交易行": self.jx3cmd.jx3_jiaoyihang,
"掉落": self.jx3cmd.jx3_diaoluo,
"开服推送": self.jx3cmd.jx3_kaifhujiank,
"新闻推送": self.jx3cmd.jx3_xinwenzhixun,
"刷马推送": self.jx3cmd.jx3_shuamamsg,
+2 -1
View File
@@ -1,9 +1,10 @@
name: astrbot_plugin_jx3
display_name: 剑网三游戏数据查询工具
desc: 通过接口调用剑网三API接口获取游戏数据,处理发送。
version: v2.3
version: v2.4
author: 飞翔大野猪
repo: https://github.com/qsc20001102/astrbot_plugin_jx3
astrbot_version: ">=4.11.0"
support_platforms:
- aiocqhttp
- weixin_oc
+3 -1
View File
@@ -1,3 +1,5 @@
matplotlib
aiofiles
aiosqlite
aiosqlite
aiohttp
apscheduler
+132
View File
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>掉落记录</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1080px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 17px;
}
th, td {
padding: 12px 10px;
border-bottom: 1px solid #eee;
font-size: 15px;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.item-col {
min-width: 120px;
color: #d93939;
font-weight: 800;
white-space: nowrap;
}
.server-col {
min-width: 90px;
text-align: center;
white-space: nowrap;
}
.map-col {
max-width: 260px;
color: #333;
word-break: break-word;
line-height: 1.45;
}
.role-col {
max-width: 260px;
color: #333;
font-weight: 700;
word-break: break-word;
line-height: 1.45;
}
.time-col {
min-width: 150px;
color: #60657a;
text-align: center;
white-space: nowrap;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ name }} 掉落记录</h1>
<div class="meta">{{ server }} · 数量:{{ limit }} · 更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>物品名称</th>
<th>服务器</th>
<th>地点</th>
<th>角色名称</th>
<th>时间</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="item-col">{{ item.item_name }}</td>
<td class="server-col">{{ item.server }}</td>
<td class="map-col">{{ item.map_name }}</td>
<td class="role-col">{{ item.role_name }}</td>
<td class="time-col">{{ item.time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+36 -4
View File
@@ -164,20 +164,52 @@ body {
<div class="command"><div class="cmd-name">的卢记录</div><div class="cmd-usage">的卢 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">烟花记录</div><div class="cmd-usage">烟花 角色名 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">骗子查询</div><div class="cmd-usage">骗子 QQ号</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">角色奇遇</div><div class="cmd-usage">查询 角色名 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">奇遇统计</div><div class="cmd-usage">统计 奇遇名称 [服务器]</div><div class="cmd-desc">统计指定奇遇触发次数</div></div>
<div class="command"><div class="cmd-name">角色奇遇</div><div class="cmd-usage">奇遇 角色名 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">未做奇遇</div><div class="cmd-usage">未做奇遇 角色名 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">奇遇统计</div><div class="cmd-usage">奇遇统计 奇遇名称 [服务器]</div><div class="cmd-desc">统计指定奇遇触发次数</div></div>
<div class="command"><div class="cmd-name">近期奇遇</div><div class="cmd-usage">近期奇遇 [服务器]</div><div class="cmd-desc">查询指定服务器最近触发的奇遇记录</div></div>
<div class="command"><div class="cmd-name">奇遇汇总</div><div class="cmd-usage">奇遇汇总 [天数] [服务器]</div><div class="cmd-desc">统计指定服务器最近一段时间的奇遇触发汇总</div></div>
<div class="command"><div class="cmd-name">名剑战绩</div><div class="cmd-usage">战绩 角色名 [服务器] [模式]</div><div class="cmd-desc">33 22</div></div>
<div class="command"><div class="cmd-name">名剑排行</div><div class="cmd-usage">排行 [数量] [模式]</div><div class="cmd-desc">33 22</div></div>
<div class="command"><div class="cmd-name">名剑统计</div><div class="cmd-usage">名剑统计 [模式]</div><div class="cmd-desc">22 33 55</div></div>
<div class="command"><div class="cmd-name">副本招募</div><div class="cmd-usage">招募 副本名称 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">拜师列表</div><div class="cmd-usage">拜师 [搜索关键词] [服务器]</div><div class="cmd-desc">查询徒弟找师傅信息</div></div>
<div class="command"><div class="cmd-name">收徒列表</div><div class="cmd-usage">收徒 [搜索关键词] [服务器]</div><div class="cmd-desc">查询师傅找徒弟信息</div></div>
<div class="command"><div class="cmd-name">名士五十强</div><div class="cmd-usage">名士五十强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">老江湖五十强</div><div class="cmd-usage">老江湖五十强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">兵甲藏家五十强</div><div class="cmd-usage">兵甲藏家五十强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">名师五十强</div><div class="cmd-usage">名师五十强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">阵营英雄五十强</div><div class="cmd-usage">阵营英雄五十强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">薪火相传五十强</div><div class="cmd-usage">薪火相传五十强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">庐园广记一百强</div><div class="cmd-usage">庐园广记一百强 [服务器]</div><div class="cmd-desc">查询风云录角色榜单</div></div>
<div class="command"><div class="cmd-name">浩气神兵宝甲五十强</div><div class="cmd-usage">浩气神兵宝甲五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">恶人神兵宝甲五十强</div><div class="cmd-usage">恶人神兵宝甲五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">浩气爱心帮会五十强</div><div class="cmd-usage">浩气爱心帮会五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">恶人爱心帮会五十强</div><div class="cmd-usage">恶人爱心帮会五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">赛季恶人五十强</div><div class="cmd-usage">赛季恶人五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">赛季浩气五十强</div><div class="cmd-usage">赛季浩气五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">上周恶人五十强</div><div class="cmd-usage">上周恶人五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">上周浩气五十强</div><div class="cmd-usage">上周浩气五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">本周恶人五十强</div><div class="cmd-usage">本周恶人五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">本周浩气五十强</div><div class="cmd-usage">本周浩气五十强 [服务器]</div><div class="cmd-desc">查询风云录帮会榜单</div></div>
<div class="command"><div class="cmd-name">掉落记录</div><div class="cmd-usage">掉落 物品名称 [数量] [服务器]</div><div class="cmd-desc">查询团队秘境贵重物品掉落记录</div></div>
<div class="command"><div class="cmd-name">角色信息</div><div class="cmd-usage">角色 名称 [服务器]</div><div class="cmd-desc">查询角色基础信息</div></div>
<div class="command"><div class="cmd-name">角色名片</div><div class="cmd-usage">名片 角色名 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">角色名片</div><div class="cmd-usage">名片 角色名 [服务器]</div><div class="cmd-desc">查询角色当前名片</div></div>
<div class="command"><div class="cmd-name">所有名片</div><div class="cmd-usage">所有名片 角色名 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">随机名片</div><div class="cmd-usage">随机 职业 体型 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">刷马</div><div class="cmd-usage">刷马 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">角色百战</div><div class="cmd-usage">精耐 角色名 [服务器]</div><div class="cmd-desc">查询角色百战精力耐力和技能列表</div></div>
<div class="command"><div class="cmd-name">心法阵眼</div><div class="cmd-usage">阵眼 心法</div><div class="cmd-desc">查询指定心法阵眼效果</div></div>
<div class="command"><div class="cmd-name">奇穴详情</div><div class="cmd-usage">奇穴 心法</div><div class="cmd-desc">查询指定心法奇穴详情</div></div>
<div class="command"><div class="cmd-name">技能详情</div><div class="cmd-usage">技能 心法</div><div class="cmd-desc">查询指定心法技能详情</div></div>
<div class="command"><div class="cmd-name">资历排行</div><div class="cmd-usage">资历排行 职业 [服务器]</div><div class="cmd-desc">查询指定职业资历排行榜</div></div>
<div class="command"><div class="cmd-name">马场刷新</div><div class="cmd-usage">刷马 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">金价查询</div><div class="cmd-usage">金价 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">外观物价</div><div class="cmd-usage">物价 外观名称 [服务器]</div><div class="cmd-desc"></div></div>
<div class="command"><div class="cmd-name">八卦记录</div><div class="cmd-usage">八卦 类型</div><div class="cmd-desc">818 616 避雷</div></div>
<div class="command"><div class="cmd-name">交易行</div><div class="cmd-usage">交易行 物品名称 [服务器]</div><div class="cmd-desc"></div></div>
</div>
</div>
+158
View File
@@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>技能详情</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1120px;
margin: 0 auto;
}
h1 {
font-size: 34px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
.section {
margin-bottom: 24px;
}
.section-title {
display: flex;
align-items: center;
gap: 10px;
margin: 0 0 12px 0;
color: #222;
font-size: 24px;
font-weight: 800;
}
.section-title::before {
content: "";
display: block;
width: 5px;
height: 30px;
background: #2f74d0;
border-radius: 3px;
}
.cards {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
}
.card {
display: grid;
grid-template-columns: 54px minmax(0, 1fr);
gap: 12px;
background: white;
border-radius: 12px;
padding: 14px;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
.icon {
width: 48px;
height: 48px;
border-radius: 8px;
object-fit: cover;
background: #f1f2f6;
}
.head {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 8px;
}
.name {
color: #222;
font-size: 18px;
font-weight: 800;
line-height: 1.25;
}
.tag {
color: #5d6680;
background: #eef2f8;
border-radius: 999px;
padding: 2px 8px;
font-size: 13px;
white-space: nowrap;
}
.desc {
color: #333;
font-size: 15px;
line-height: 1.55;
word-break: break-word;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ name }} 技能详情</h1>
<div class="meta">更新时间:{{ update_time }}</div>
{% for group in groups %}
<div class="section">
<div class="section-title">{{ group.title }}</div>
<div class="cards">
{% for skill in group.skills %}
<div class="card">
{% if skill.icon %}
<img class="icon" src="{{ skill.icon }}" alt="{{ skill.name }}">
{% else %}
<div class="icon"></div>
{% endif %}
<div>
<div class="head">
<span class="name">{{ skill.name }}</span>
{% if skill.interval %}
<span class="tag">{{ skill.interval }}</span>
{% endif %}
{% if skill.distance %}
<span class="tag">{{ skill.distance }}</span>
{% endif %}
{% if skill.release_type %}
<span class="tag">{{ skill.release_type }}</span>
{% endif %}
{% if skill.weapon %}
<span class="tag">{{ skill.weapon }}</span>
{% endif %}
</div>
<div class="desc">{{ skill.desc }}</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</body>
</html>
+165
View File
@@ -0,0 +1,165 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>精耐查询</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 980px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 22px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
.summary {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
margin-bottom: 22px;
}
.stat {
background: white;
border-radius: 12px;
padding: 18px 14px;
text-align: center;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
.label {
color: #7a7f99;
font-size: 16px;
margin-bottom: 8px;
}
.value {
color: #d93939;
font-size: 30px;
line-height: 1;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 17px;
}
th, td {
padding: 12px 10px;
border-bottom: 1px solid #eee;
font-size: 15px;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.skill-col {
width: 34%;
font-weight: 800;
color: #333;
word-break: break-word;
line-height: 1.45;
}
.leader-col {
width: 30%;
color: #333;
word-break: break-word;
line-height: 1.45;
}
.color-col,
.level-col {
text-align: center;
white-space: nowrap;
font-weight: 700;
}
.level-col {
color: #d93939;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ server }} - {{ role_name }}</h1>
<div class="meta">更新时间:{{ update_time }}</div>
<div class="summary">
<div class="stat">
<div class="label">精力</div>
<div class="value">{{ skill_energy }}</div>
</div>
<div class="stat">
<div class="label">耐力</div>
<div class="value">{{ skill_stamina }}</div>
</div>
<div class="stat">
<div class="label">技能数量</div>
<div class="value">{{ skill_count }}</div>
</div>
</div>
<table>
<thead>
<tr>
<th>技能名称</th>
<th>首领</th>
<th>破绽颜色</th>
<th>技能等级</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="skill-col">{{ item.skill_name }}</td>
<td class="leader-col">{{ item.leader_name }}</td>
<td class="color-col">{{ item.skill_color_text }}</td>
<td class="level-col">{{ item.skill_level }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+109
View File
@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>近期奇遇</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1040px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 18px;
}
th, td {
padding: 14px 12px;
border-bottom: 1px solid #eee;
font-size: 16px;
white-space: nowrap;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.event-col {
font-weight: 700;
color: #333;
}
.role-col {
color: #333;
}
.time-col {
color: #60657a;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ server }} 近期奇遇</h1>
<div class="meta">更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>区服</th>
<th>角色</th>
<th>奇遇名称</th>
<th>触发时间</th>
</tr>
</thead>
<tbody>
{% for m in items %}
<tr>
<td>{{ m.server }}</td>
<td class="role-col">{{ m.name }}</td>
<td class="event-col">{{ m.event }}</td>
<td class="time-col">{{ m.time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+124
View File
@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>名剑统计</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 640px;
margin: 0 auto;
}
h1 {
font-size: 30px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 18px;
}
th, td {
padding: 12px 10px;
border-bottom: 1px solid #eee;
font-size: 15px;
white-space: nowrap;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.school {
display: flex;
align-items: center;
gap: 8px;
font-weight: 700;
color: #333;
}
.school-icon {
width: 32px;
height: 32px;
border-radius: 50%;
object-fit: contain;
flex: 0 0 auto;
}
.num-col {
color: #d93939;
font-weight: 700;
text-align: center;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>名剑统计(前1000) · {{ mode }}</h1>
<div class="meta">更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>门派</th>
<th>当前赛季数量</th>
<th>上赛季数量</th>
</tr>
</thead>
<tbody>
{% for m in items %}
<tr>
<td>
<div class="school">
{% if icons.sect.get(m.name) %}
<img class="school-icon" src="{{ icons.sect[m.name] }}" alt="{{ m.name }}">
{% endif %}
<span>{{ m.name }}</span>
</div>
</td>
<td class="num-col">{{ m.this }}</td>
<td class="num-col">{{ m.last }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+160
View File
@@ -0,0 +1,160 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>奇穴详情</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1120px;
margin: 0 auto;
}
h1 {
font-size: 34px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
.section {
margin-bottom: 24px;
}
.section-title {
display: flex;
align-items: center;
gap: 10px;
margin: 0 0 12px 0;
color: #222;
font-size: 24px;
font-weight: 800;
}
.section-title::before {
content: "";
display: block;
width: 5px;
height: 30px;
background: #d93939;
border-radius: 3px;
}
.cards {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
}
.card {
display: grid;
grid-template-columns: 54px minmax(0, 1fr);
gap: 12px;
background: white;
border-radius: 12px;
padding: 14px;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
.icon {
width: 48px;
height: 48px;
border-radius: 8px;
object-fit: cover;
background: #f1f2f6;
}
.head {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 8px;
}
.name {
color: #222;
font-size: 18px;
font-weight: 800;
line-height: 1.25;
}
.tag {
color: white;
background: #d93939;
border-radius: 999px;
padding: 2px 8px;
font-size: 13px;
font-weight: 700;
white-space: nowrap;
}
.interval {
color: #7a7f99;
background: #f1f2f6;
border-radius: 999px;
padding: 2px 8px;
font-size: 13px;
white-space: nowrap;
}
.desc {
color: #333;
font-size: 15px;
line-height: 1.55;
word-break: break-word;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ name }} 奇穴详情</h1>
<div class="meta">更新时间:{{ update_time }}</div>
{% for group in groups %}
<div class="section">
<div class="section-title">{{ group['title'] }}</div>
<div class="cards">
{% for item in group.talents %}
<div class="card">
{% if item['icon'] %}
<img class="icon" src="{{ item['icon'] }}" alt="{{ item['name'] }}">
{% else %}
<div class="icon"></div>
{% endif %}
<div>
<div class="head">
<span class="name">{{ item['name'] }}</span>
<span class="tag">{{ item['class_text'] }}</span>
{% if item['interval'] %}
<span class="interval">{{ item['interval'] }}</span>
{% endif %}
</div>
<div class="desc">{{ item['desc'] }}</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</body>
</html>
+117
View File
@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>奇遇汇总</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1080px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 18px;
}
th, td {
padding: 14px 12px;
border-bottom: 1px solid #eee;
font-size: 16px;
white-space: nowrap;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.event-col {
font-weight: 700;
color: #333;
}
.count-col {
color: #d93939;
font-weight: 700;
text-align: center;
}
.role-col {
color: #333;
}
.time-col {
color: #60657a;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ server }} 奇遇汇总</h1>
<div class="meta">最近 {{ num }} 天 · 更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>区服</th>
<th>奇遇名称</th>
<th>触发次数</th>
<th>最近角色</th>
<th>最近时间</th>
</tr>
</thead>
<tbody>
{% for m in items %}
<tr>
<td>{{ m.server }}</td>
<td class="event-col">{{ m.event }}</td>
<td class="count-col">{{ m.count }}</td>
<td class="role-col">{{ m.latest_name }}</td>
<td class="time-col">{{ m.latest_time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+158
View File
@@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>角色榜单</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1120px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 17px;
}
th, td {
padding: 12px 10px;
border-bottom: 1px solid #eee;
font-size: 15px;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.rank-col,
.level-col,
.camp-col,
.score-col {
white-space: nowrap;
text-align: center;
}
.rank-col {
width: 56px;
color: #d93939;
font-weight: 800;
}
.force {
display: flex;
align-items: center;
gap: 8px;
min-width: 108px;
font-weight: 700;
color: #333;
white-space: nowrap;
}
.force-icon {
width: 30px;
height: 30px;
border-radius: 50%;
object-fit: contain;
flex: 0 0 auto;
}
.role-col {
min-width: 120px;
font-weight: 700;
color: #333;
white-space: nowrap;
}
.tong-col {
max-width: 260px;
word-break: break-word;
color: #333;
}
.score-col {
color: #d93939;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ rank_name }}</h1>
<div class="meta">{{ server }} · 更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>排名</th>
<th>职业</th>
<th>角色名称</th>
<th>等级</th>
<th>阵营</th>
<th>帮会</th>
<th>排行积分</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="rank-col">{{ loop.index }}</td>
<td>
<div class="force">
{% if icons.sect.get(item.force_name) %}
<img class="force-icon" src="{{ icons.sect[item.force_name] }}" alt="{{ item.force_name }}">
{% endif %}
<span>{{ item.force_name }}</span>
</div>
</td>
<td class="role-col">{{ item.role_name }}</td>
<td class="level-col">{{ item.role_level }}</td>
<td class="camp-col">{{ item.camp_name }}</td>
<td class="tong-col">{{ item.tong_name }}</td>
<td class="score-col">{{ item.total_score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+141
View File
@@ -0,0 +1,141 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>帮会榜单</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1040px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 17px;
}
th, td {
padding: 12px 10px;
border-bottom: 1px solid #eee;
font-size: 15px;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.rank-col,
.people-col,
.score-col {
white-space: nowrap;
text-align: center;
}
.rank-col {
width: 56px;
color: #d93939;
font-weight: 800;
}
.tong-col {
min-width: 220px;
font-weight: 800;
color: #333;
word-break: break-word;
}
.master-col {
min-width: 150px;
color: #333;
word-break: break-word;
}
.castle-col {
min-width: 110px;
color: #60657a;
word-break: break-word;
}
.people-col {
color: #333;
font-variant-numeric: tabular-nums;
}
.score-col {
color: #d93939;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ rank_name }}</h1>
<div class="meta">{{ server }} · 更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>排名</th>
<th>帮会名称</th>
<th>帮主</th>
<th>据点</th>
<th>人数</th>
<th>排行积分</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="rank-col">{{ loop.index }}</td>
<td class="tong-col">{{ item.tong_name }}</td>
<td class="master-col">{{ item.master_name }}</td>
<td class="castle-col">{{ item.castle_name }}</td>
<td class="people-col">{{ item.now_count }}/{{ item.max_count }}</td>
<td class="score-col">{{ item.total_score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+151
View File
@@ -0,0 +1,151 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>师徒招募</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1280px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 18px;
}
th, td {
padding: 14px 12px;
border-bottom: 1px solid #eee;
font-size: 16px;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.force-col {
min-width: 120px;
}
.force {
display: flex;
align-items: center;
gap: 8px;
font-weight: 700;
color: #333;
white-space: nowrap;
}
.force-icon {
width: 32px;
height: 32px;
border-radius: 50%;
object-fit: contain;
flex: 0 0 auto;
}
.name-col {
font-weight: 700;
color: #333;
white-space: nowrap;
}
.small-col {
white-space: nowrap;
text-align: center;
}
.comment-col {
max-width: 420px;
line-height: 1.5;
word-break: break-word;
color: #333;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ title }}</h1>
<div class="meta">
{{ server }}
{% if keyword %} · 关键词:{{ keyword }}{% endif %}
· 更新时间:{{ update_time }}
</div>
<table>
<thead>
<tr>
<th>职业</th>
<th>角色名称</th>
<th>等级</th>
<th>体型</th>
<th>帮会</th>
<th>阵营</th>
<th>信息</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="force-col">
<div class="force">
{% if icons.sect.get(item.forceName) %}
<img class="force-icon" src="{{ icons.sect[item.forceName] }}" alt="{{ item.forceName }}">
{% endif %}
<span>{{ item.forceName }}</span>
</div>
</td>
<td class="name-col">{{ item.roleName }}</td>
<td class="small-col">{{ item.roleLevel }}</td>
<td class="small-col">{{ item.bodyName }}</td>
<td>{{ item.tongName }}</td>
<td class="small-col">{{ item.campName }}</td>
<td class="comment-col">{{ item.comment }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
+139
View File
@@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>未做奇遇</title>
<style>
body {
margin: 0;
padding: 24px;
background: #f5f7fb;
color: #2c2c33;
font-family: "Microsoft YaHei", Arial, sans-serif;
}
.header {
margin-bottom: 24px;
color: #1f2a44;
}
.title {
font-size: 34px;
font-weight: 800;
margin-bottom: 8px;
}
.meta {
font-size: 20px;
color: #7a7f99;
}
.section {
margin-bottom: 32px;
}
.section-title {
font-size: 36px;
font-weight: bold;
margin-bottom: 16px;
border-left: 4px solid #4f7cff;
padding-left: 10px;
color: #1f2a44;
}
.card-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.card {
background: #ffffff;
border-radius: 8px;
padding: 16px 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
min-height: 90px;
}
.card img {
width: 100%;
max-width: 180px;
height: auto;
object-fit: contain;
margin-bottom: 6px;
}
.event-name {
font-size: 22px;
font-weight: 600;
margin-bottom: 4px;
color: #2b3a67;
}
.time {
font-size: 22px;
color: #7a7f99;
}
.empty {
background: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.06);
color: #7a7f99;
font-size: 20px;
padding: 22px;
}
</style>
</head>
<body>
<div class="header">
<div class="title">未做奇遇</div>
<div class="meta">{{ server }} · {{ name }}</div>
</div>
<div class="section">
<div class="section-title">普通奇遇({{ ptqy|length if ptqy else 0 }}</div>
{% if ptqy %}
<div class="card-container">
{% for item in ptqy %}
<div class="card">
{% if icons.serendipity.get(item.event) %}
<img src="{{ icons.serendipity[item.event] }}" alt="{{ item.event }}">
{% else %}
<div class="event-name">{{ item.event }}</div>
{% endif %}
<div class="time">{{ item.time }}</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty">暂无未做普通奇遇</div>
{% endif %}
</div>
<div class="section">
<div class="section-title">绝世奇遇({{ jsqy|length if jsqy else 0 }}</div>
{% if jsqy %}
<div class="card-container">
{% for item in jsqy %}
<div class="card">
{% if icons.serendipity.get(item.event) %}
<img src="{{ icons.serendipity[item.event] }}" alt="{{ item.event }}">
{% else %}
<div class="event-name">{{ item.event }}</div>
{% endif %}
<div class="time">{{ item.time }}</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty">暂无未做绝世奇遇</div>
{% endif %}
</div>
</body>
</html>
+71 -16
View File
@@ -107,7 +107,8 @@ table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
font-size: 22px;
font-size: 18px;
table-layout: fixed;
}
thead {
@@ -115,7 +116,7 @@ thead {
}
th, td {
padding: 10px;
padding: 8px 6px;
text-align: center;
}
@@ -154,6 +155,36 @@ tbody tr:nth-child(odd) {
color: #f5a623;
font-weight: bold;
}
.time-col {
width: 170px;
font-size: 16px;
font-variant-numeric: tabular-nums;
}
.duration-col {
width: 92px;
}
.kungfu-col {
width: 150px;
}
.result-col {
width: 64px;
}
.score-col {
width: 104px;
}
.grade-col {
width: 96px;
}
.mvp-col {
width: 58px;
}
</style>
</head>
@@ -210,28 +241,30 @@ tbody tr:nth-child(odd) {
<table>
<thead>
<tr>
<th>对战时长</th>
<th>心法</th>
<th>胜负</th>
<th>积分变化</th>
<th>最终积分</th>
<th>平均段位</th>
<th>MVP</th>
<th class="time-col">开始时间</th>
<th class="duration-col">对战时长</th>
<th class="kungfu-col">心法</th>
<th class="result-col">胜负</th>
<th class="score-col">积分变化</th>
<th class="score-col">最终积分</th>
<th class="grade-col">平均段位</th>
<th class="mvp-col">MVP</th>
</tr>
</thead>
<tbody>
{% for m in history %}
<tr>
<td>{{ m.endTime - m.startTime }}</td>
<td>{{ m.kungfu }}</td>
<td class="{{ 'win' if m.won else 'lose' }}">{{ '胜' if m.won else '负' }}</td>
<td class="{{ 'mmr-up' if m.mmr > 0 else 'mmr-down' }}">
<td class="time-col start-time" data-ts="{{ m.startTime }}">{{ m.startTime }}</td>
<td class="duration-col">{{ m.endTime - m.startTime }}</td>
<td class="kungfu-col">{{ m.kungfu }}</td>
<td class="result-col {{ 'win' if m.won else 'lose' }}">{{ '胜' if m.won else '负' }}</td>
<td class="score-col {{ 'mmr-up' if m.mmr > 0 else 'mmr-down' }}">
{{ m.mmr }}
</td>
<td>{{ m.totalMmr }}</td>
<td>{{ m.avgGrade }}</td>
<td class="{{ 'mvp' if m.mvp else '' }}">
<td class="score-col">{{ m.totalMmr }}</td>
<td class="grade-col">{{ m.avgGrade }}</td>
<td class="mvp-col {{ 'mvp' if m.mvp else '' }}">
{{ '是' if m.mvp else '-' }}
</td>
</tr>
@@ -240,5 +273,27 @@ tbody tr:nth-child(odd) {
</table>
</div>
<script>
document.querySelectorAll(".start-time").forEach(function (cell) {
var raw = cell.dataset.ts || cell.textContent.trim();
var ts = Number(raw);
if (!Number.isFinite(ts) || ts <= 0) {
cell.textContent = raw || "-";
return;
}
var date = new Date(ts * 1000);
var pad = function (n) { return String(n).padStart(2, "0"); };
cell.textContent = [
date.getFullYear(),
pad(date.getMonth() + 1),
pad(date.getDate())
].join("-") + " " + [
pad(date.getHours()),
pad(date.getMinutes()),
pad(date.getSeconds())
].join(":");
});
</script>
</body>
</html>
+163
View File
@@ -0,0 +1,163 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>资历排行</title>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
margin: 0;
padding: 20px;
color: #2c2c33;
}
.container {
max-width: 1040px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin: 0 0 8px 0;
color: #222;
font-weight: 800;
text-align: center;
}
.meta {
margin-bottom: 24px;
color: #7a7f99;
font-size: 16px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
text-align: left;
}
thead {
background: #d93939;
color: white;
font-size: 17px;
}
th, td {
padding: 12px 10px;
border-bottom: 1px solid #eee;
font-size: 15px;
vertical-align: middle;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
.rank-col,
.server-col,
.score-col {
white-space: nowrap;
text-align: center;
}
.rank-col {
width: 56px;
color: #d93939;
font-weight: 800;
}
.role,
.force {
display: flex;
align-items: center;
gap: 8px;
min-width: 150px;
font-weight: 700;
color: #333;
white-space: nowrap;
}
.avatar {
width: 34px;
height: 34px;
border-radius: 50%;
object-fit: cover;
flex: 0 0 auto;
background: #eef2f8;
}
.force-icon {
width: 30px;
height: 30px;
border-radius: 50%;
object-fit: contain;
flex: 0 0 auto;
background: #eef2f8;
}
.server-col {
color: #333;
}
.score-col {
color: #d93939;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<h1>{{ school }} 资历排行</h1>
<div class="meta">{{ server }} 更新时间:{{ update_time }}</div>
<table>
<thead>
<tr>
<th>排名</th>
<th>角色</th>
<th>职业</th>
<th>服务器</th>
<th>资历值</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="rank-col">{{ loop.index }}</td>
<td>
<div class="role">
{% if item.avatarUrl %}
<img class="avatar" src="{{ item.avatarUrl }}" alt="{{ item.roleName }}">
{% endif %}
<span>{{ item.roleName }}</span>
</div>
</td>
<td>
<div class="force">
{% set force_icon = item.forceIcon or icons.sect.get(item.forceName) %}
{% if force_icon %}
<img class="force-icon" src="{{ force_icon }}" alt="{{ item.forceName }}">
{% endif %}
<span>{{ item.forceName }}</span>
</div>
</td>
<td class="server-col">{{ item.serverName }}</td>
<td class="score-col">{{ item.seniority }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>