diff --git a/README.md b/README.md index c32ba0b..a43d05e 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,15 @@ 试炼排行:试炼排行 服务器 心法 【物价交易】 阵营拍卖:阵营拍卖 服务器 [物品] [数量] - +的卢拍卖:的卢 服务器 +金价行情:金价 服务器 +物品价格:物价 外观名称 [服务器] +成本计算:成本 服务器 物品名称 +编号搜索:看号 万宝楼编号 +【阵营战场】 +帮战记录:帮战 服务器 +阵营沙盘:沙盘 服务器 +诛恶事件:诛恶 服务器 ## 安装与依赖 diff --git a/core/aijx3_data.py b/core/aijx3_data.py new file mode 100644 index 0000000..3066243 --- /dev/null +++ b/core/aijx3_data.py @@ -0,0 +1,153 @@ +import json +import html +import re +from datetime import datetime, timedelta +from typing import Dict, Any, Optional, List, Union +from inspect import isawaitable +from typing import Any, Awaitable, Callable, Dict, Optional + +from astrbot.api import logger +from astrbot.api import AstrBotConfig +import astrbot.api.message_components as Comp + +from .request import APIClient +from .sqlite import AsyncSQLiteDB +from .fun_basic import load_template,gold_to_parts,week_to_num,compare_date_str,format_time,format_remaining + + +class AIJX3Service: + def __init__(self, config: AstrBotConfig, sqlite: AsyncSQLiteDB, cache_sqlite: Optional[AsyncSQLiteDB] = None): + # 实例化 API Client + self._api: APIClient = APIClient() + # 引用插件配置文件 + self._config = config + # 引用sqlite + self._sql_db = sqlite + self._cache_db = cache_sqlite or sqlite + + + + async def close(self): + """释放底层 APIClient 资源""" + if self._api: + await self._api.close() + + + def _init_return_data(self) -> Dict[str, Any]: + """初始化标准的返回数据结构""" + return { + "code": 0, + "msg": "功能函数未执行", + "data": {}, + "temp": "", + "icons": {} + } + + + async def _base_request( + self, + api_path: str, + params: Optional[Dict[str, Any]] = None, + out: Optional[str] = "data" + ) -> Optional[Any]: + """ + 基础请求封装,处理配置获取和API调用。 + """ + try: + if not self._api: + logger.error("API client is not initialized") + return None + + base_url = "https://www.jianxiachaguan.cn" + api_url = base_url + api_path + data = await self._api.post(api_url, data=params, out_key=out) + + if not data: + logger.warning(f"获取接口信息失败或返回空数据: {api_url}") + + return data + + except Exception as e: + logger.error(f"基础请求调用出错 ({api_path}): {e}") + return None + + + async def _request_api( + self, + path: str, + params: Dict[str, Any], + processor: Optional[ + Callable[[Any, Dict[str, Any]], Any | Awaitable[Any]] + ] = None, + template: Optional[str] = None, + ) -> Dict[str, Any]: + """通用接口请求与模板处理。""" + return_data = self._init_return_data() + + data = await self._base_request(path, params) + if data is None: + return_data["msg"] = "获取接口信息失败" + return return_data + + try: + await processor(data, return_data) + except Exception as e: + logger.exception(f"数据处理时出错: {e}") + return_data["msg"] = "处理接口返回信息时出错" + return return_data + + # template 为空时不加载模板 + if template: + try: + return_data["temp"] = await load_template(template) + except FileNotFoundError as e: + logger.error(f"加载模板失败: {e}") + return_data["msg"] = "系统错误:模板文件不存在" + return return_data + + return_data["code"] = 200 + return return_data + + + async def shapan(self, server: str ) -> Dict[str, Any]: + """区服沙盘""" + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + pic_url = data.get("picUrl") + if pic_url: + return_data["data"] = pic_url + else: + return_data["msg"] = "接口未返回图片URL" + return return_data + + return await self._request_api( + path="/api2/aijx3-jxcg/game/get-sand-table-img", + params={"serverName": server}, + processor=processor, + template="" + ) + return_data = self._init_return_data() + + # 1. 构造请求参数 + params = {"serverName": server} + + # 2. 调用基础请求 + data: Optional[Dict[str, Any]] = await self._base_request( + "aijx3_shapan", "POST", params=params + ) + + if not data: + return_data["msg"] = "获取接口信息失败" + return return_data + + # 3. 处理返回数据 (直接提取图片 URL) + pic_url = data.get("picUrl") + if pic_url: + return_data["data"] = pic_url + else: + return_data["msg"] = "接口未返回图片URL" + return return_data + + return_data["code"] = 200 + + return return_data + diff --git a/core/jx3api_data.py b/core/jx3api_data.py index 67a6a03..486d870 100644 --- a/core/jx3api_data.py +++ b/core/jx3api_data.py @@ -1,4 +1,6 @@ import json +import html +import re from datetime import datetime, timedelta from typing import Dict, Any, Optional, List, Union from inspect import isawaitable @@ -563,6 +565,167 @@ class JX3APIService: ) + async def jinjia(self, server: str, limit:str) -> Dict[str, Any]: + """金价行情""" + # 数据处理 + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + return_data["data"]["items"] = data + + return await self._request_api( + path="/trade/demon", + params={"server": server, "limit": limit, "token": self.token}, + processor=processor, + template="jinjia.html" + ) + + + async def wujia(self, Name: str, server:str) -> Dict[str, Any]: + """物价查询""" + # 数据处理 + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + return_data["data"] = data + + return await self._request_api( + path="/trade/records", + params={"name": Name,"token": self.token, "server": server}, + processor=processor, + template="wujia.html" + ) + + + async def chengbeng(self, Name: str, server:str, source: int) -> Dict[str, Any]: + """成本计算""" + # 数据处理 + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + return_data["data"] = data + + return await self._request_api( + path="/trade/manufacture", + params={"name": Name,"token": self.token, "server": server, "source": source}, + processor=processor, + template="chengbeng.html" + ) + + async def bianhao(self, id: str) -> Dict[str, Any]: + """编号搜索""" + # 数据处理 + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + if not isinstance(data, dict): + return_data["data"] = "账号角色数据格式错误" + return + + # 同时兼容完整接口数据和直接传入 data 字段 + data = data.get("data", data) + + if not isinstance(data, dict): + return_data["data"] = "账号角色数据为空" + return + + # 将 replyContent 中的 HTML 转换为纯文本 + detail = str(data.get("replyContent") or "") + detail = re.sub(r"", "\n", detail, flags=re.IGNORECASE) + detail = re.sub(r"<[^>]+>", "", detail) + detail = html.unescape(detail).strip() or "暂无账号详细信息" + + # 交易状态 + trade_status = { + 1: "公示中", + 2: "出售中", + 3: "出售中", + 4: "已售出", + 5: "已下架", + }.get(data.get("tradeStatus"), f"状态码 {data.get('tradeStatus', '未知')}") + + # 调价记录,接口中的时间为毫秒时间戳 + update_prices = data.get("updatePrices") or [] + update_price_text = "\n".join( + f"{index}. {format_time(int(item.get('updateTime') or 0) // 1000)}:" + f"{item.get('updatePrice', 0)} 元" + for index, item in enumerate(update_prices, start=1) + if isinstance(item, dict) + ) or "暂无调价记录" + + return_data["data"] = ( + f"【万宝楼账号】\n" + f"{data.get('replyTitle') or '暂无标题'}\n\n" + + f"【角色信息】\n" + f"区服:{data.get('serverName') or '未知'}\n" + f"角色:{data.get('roleName') or '未知'}\n" + f"等级:{data.get('roleLevel') or 0}\n" + f"门派:{data.get('forceName') or '未知'}\n" + f"体型:{data.get('bodyName') or '未知'}\n" + f"阵营:{data.get('campName') or '未知'}\n\n" + + f"【账号数据】\n" + f"装备分数:{data.get('equipScore') or 0}\n" + f"江湖资历:{data.get('seniorityNum') or 0}\n" + f"约见次数:{data.get('meetingNum') or 0}\n" + f"关注人数:{data.get('followNum') or 0}\n\n" + + f"【交易信息】\n" + f"挂牌价格:{data.get('priceNum') or 0} 元\n" + f"交易状态:{trade_status}\n" + f"商品编号:{data.get('id') or '未知'}\n" + f"发布时间:{format_time(data.get('replyTime') or 0)}\n\n" + + f"【调价记录】\n" + f"{update_price_text}\n\n" + + f"【账号详情】\n" + f"{detail}" + ) + + return await self._request_api( + path="/trade/wanbaolou", + params={"id": id,"token": self.token}, + processor=processor, + template="" + ) + + + async def bangzhanjilu(self, server: str) -> Dict[str, Any]: + """帮战记录""" + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + for item in data: + item["startTime"] = format_time(item["startTime"]) + item["durationSeconds"] = format_remaining(item["durationSeconds"]) + item["endTime"] = format_time(item["endTime"]) + + return_data["data"] = { + "items": data, + "server": server, + "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + } + + return await self._request_api( + path="/battle/records", + params={"server": server}, + processor=processor, + template="bangzhanjilu.html" + ) + + + async def zhueevent(self,server: str,limit: str) -> Dict[str, Any]: + """诛恶事件""" + async def processor(data: Any, return_data: Dict[str, Any]) -> None: + for item in data: + item["time"] = format_time(item["time"]) + + return_data["data"] = { + "items": data, + "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S") + } + + return await self._request_api( + path="/wicked/records", + params={"token": self.token, "server": server, "limit": limit}, + processor=processor, + template="zhueevent.html" + ) + + + @@ -1313,33 +1476,7 @@ class JX3APIService: return return_data - async def shapan(self, server: str ) -> Dict[str, Any]: - """区服沙盘""" - return_data = self._init_return_data() - - # 1. 构造请求参数 - params = {"serverName": server} - - # 2. 调用基础请求 - data: Optional[Dict[str, Any]] = await self._base_request( - "aijx3_shapan", "POST", params=params - ) - - if not data: - return_data["msg"] = "获取接口信息失败" - return return_data - - # 3. 处理返回数据 (直接提取图片 URL) - pic_url = data.get("picUrl") - if pic_url: - return_data["data"] = pic_url - else: - return_data["msg"] = "接口未返回图片URL" - return return_data - - return_data["code"] = 200 - return return_data @@ -1417,60 +1554,7 @@ class JX3APIService: return return_data - async def zhueevent(self) -> Dict[str, Any]: - """诛恶事件""" - return_data = self._init_return_data() - - params = {"token": self.token} - - data: Optional[List[Dict[str, Any]]] = await self._base_request( - "jx3_zhueevent", "GET", params=params - ) - - if not data or not isinstance(data, list): - return_data["msg"] = "未查询到诛恶事件信息" - return return_data - - try: - items = [] - for item in data: - if not isinstance(item, dict): - continue - 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"] = "" - - items.append(item) - - if not items: - return_data["msg"] = "未查询到诛恶事件信息" - return return_data - - return_data["data"] = { - "items": items, - "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("zhueevent.html") - except FileNotFoundError as e: - logger.error(f"加载模板失败: {e}") - return_data["msg"] = "系统错误:模板文件不存在" - return return_data - - return_data["code"] = 200 - - return return_data @@ -1488,84 +1572,7 @@ class JX3APIService: - async def bangzhanjilu(self, server: str) -> Dict[str, Any]: - """帮战记录""" - return_data = self._init_return_data() - params = { - "server": server, - "token": self.token, - } - - data: Optional[List[Dict[str, Any]]] = await self._base_request( - "jx3_bangzhanjilu", "GET", params=params - ) - - if not data or not isinstance(data, list): - return_data["msg"] = "未查询到帮战记录" - return return_data - - try: - def format_time(value: Any) -> str: - if not value: - return "" - try: - return datetime.fromtimestamp(int(value)).strftime("%Y-%m-%d %H:%M:%S") - except (TypeError, ValueError, OSError): - return str(value) - - def format_duration(value: Any) -> str: - if value in (None, ""): - return "" - try: - seconds = max(0, int(value)) - except (TypeError, ValueError): - return str(value) - - hours = seconds // 3600 - minutes = (seconds % 3600) // 60 - secs = seconds % 60 - return f"{hours}时{minutes:02d}分{secs:02d}秒" - - items = [] - for item in data: - if not isinstance(item, dict): - continue - - items.append({ - "zoneName": item.get("zoneName", ""), - "serverName": item.get("serverName", ""), - "declaringTongName": item.get("declaringTongName", ""), - "acceptingTongName": item.get("acceptingTongName", ""), - "startTime": format_time(item.get("startTime")), - "matchDuration": format_duration(item.get("matchDuration")), - "endTime": format_time(item.get("endTime")), - }) - - if not items: - return_data["msg"] = "未查询到帮战记录" - return return_data - - return_data["data"] = { - "items": items, - "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("bangzhanjilu.html") - except FileNotFoundError as e: - logger.error(f"加载模板失败: {e}") - return_data["msg"] = "系统错误:模板文件不存在" - return return_data - - return_data["code"] = 200 - - return return_data async def tongzhanyy(self, server: str) -> Dict[str, Any]: @@ -2626,65 +2633,9 @@ class JX3APIService: - async def jinjia(self, server: str, limit:str) -> Dict[str, Any]: - """区服金价""" - return_data = self._init_return_data() - - - params = {"server": server, "limit": limit, "token": self.token} - data_list: Optional[List[Dict[str, Any]]] = await self._base_request("jx3_jinjia", "GET", params=params) - - if not data_list or not isinstance(data_list, list): - return_data["msg"] = "获取接口信息失败或数据格式错误" - return return_data - - # 加载模板 - try: - return_data["temp"] = await load_template("jinjia.html") - except FileNotFoundError as e: - logger.error(f"加载模板失败: {e}") - return_data["msg"] = "系统错误:模板文件不存在" - return return_data - - # 准备模板渲染数据 - try: - return_data["data"]["items"] = data_list - - except Exception as e: - logger.error(f"模板数据准备失败: {e}") - return_data["msg"] = "系统错误:模板渲染数据准备失败" - return return_data - - return_data["code"] = 200 - - return return_data - async def wujia(self, Name: str, server:str) -> Dict[str, Any]: - """物价查询""" - return_data = self._init_return_data() - - # 2. 确定外观名称和 ID - params_search = {"name": Name,"token": self.token, "server": server} - search_data: Optional[Dict[str, Any]] = await self._base_request("jx3_wujia", "GET", params=params_search) - - if not search_data: - return_data["msg"] = "未找到该外观" - return return_data - - return_data["data"] = search_data - - # 5. 加载模板 - try: - return_data["temp"] = await load_template("wujia.html") - return_data["code"] = 200 - except FileNotFoundError as e: - logger.error(f"加载模板失败: {e}") - return_data["msg"] = "系统错误:模板文件不存在" - return return_data - - return return_data async def jiaoyihang(self, name: str , server: str) -> Dict[str, Any]: diff --git a/core/message.py b/core/message.py index 661864c..6f53ae5 100644 --- a/core/message.py +++ b/core/message.py @@ -7,6 +7,7 @@ from astrbot.core.utils.session_waiter import ( ) from .jx3api_data import JX3APIService +from .aijx3_data import AIJX3Service from .async_task import AsyncTask from .bilei_data import BiLeidata @@ -36,9 +37,10 @@ class MessageBuilder: "18:剑侠录总览" ) - def __init__(self, server: str, jx3api: JX3APIService, bilei: BiLeidata, jx3at: AsyncTask, icons: dict[str, dict[str, str]]): + def __init__(self, server: str, jx3api: JX3APIService, aijx3: AIJX3Service,bilei: BiLeidata, jx3at: AsyncTask, icons: dict[str, dict[str, str]]): self.server = server self.jx3api = jx3api + self.aijx3 = aijx3 self.bilei = bilei self.jx3at = jx3at self.icons = icons @@ -419,6 +421,36 @@ class MessageBuilder: """ 的卢 服务器""" return await self.T2I_image_msg(event, lambda: self.jx3api.dilujilu(server)) + async def jinjia(self, event: AstrMessageEvent,server: str , limit:str = "15"): + """ 金价 服务器""" + return await self.T2I_image_msg(event, lambda: self.jx3api.jinjia( server,limit)) + + async def wujia(self, event: AstrMessageEvent,Name: str , server: str = ""): + """ 物价 外观名称 服务器""" + return await self.T2I_image_msg(event, lambda: self.jx3api.wujia(Name, server)) + + async def chengbeng(self, event: AstrMessageEvent, server: str ,Name: str ,source : int = 0): + """ 成本 服务器 物品名称 """ + return await self.T2I_image_msg(event, lambda: self.jx3api.chengbeng(Name, server,source)) + + async def kanhao(self, event: AstrMessageEvent,id: str): + """ 看号 万宝楼编号 """ + return await self.plain_msg(event, lambda: self.jx3api.bianhao(id)) + + async def bangzhanjilu(self, event: AstrMessageEvent, server: str): + """ 帮战 服务器""" + return await self.T2I_image_msg(event, lambda: self.jx3api.bangzhanjilu(server)) + + async def shapan(self, event: AstrMessageEvent,server: str = ""): + """ 沙盘 服务器""" + return await self.image_msg(event, lambda: self.aijx3.shapan(server)) + + async def zhueevent(self, event: AstrMessageEvent, server: str): + """ 诛恶事件 服务器""" + return await self.T2I_image_msg(event, lambda: self.jx3api.zhueevent(server,20)) + + + async def keju(self, event: AstrMessageEvent,subject: str, limit: int = 5): """ 科举""" @@ -516,9 +548,7 @@ class MessageBuilder: return await self.plain_msg(event, self.jx3api.jiemi) - async def shapan(self, event: AstrMessageEvent,server: str = ""): - """ 沙盘 服务器""" - return await self.image_msg(event, lambda: self.jx3api.shapan(self.serverdefault(server))) + async def baizhan(self, event: AstrMessageEvent): @@ -531,9 +561,6 @@ class MessageBuilder: return await self.plain_msg(event, lambda: self.jx3api.fuyaojjiutian( self.serverdefault(server))) - async def zhueevent(self, event: AstrMessageEvent): - """ 诛恶事件""" - return await self.T2I_image_msg(event, self.jx3api.zhueevent) @@ -546,9 +573,8 @@ class MessageBuilder: - async def bangzhanjilu(self, event: AstrMessageEvent, server: str = ""): - """ 帮战记录 服务器""" - return await self.T2I_image_msg(event, lambda: self.jx3api.bangzhanjilu(self.serverdefault(server))) + + async def tongzhanyy(self, event: AstrMessageEvent, server: str = ""): @@ -650,14 +676,10 @@ class MessageBuilder: - async def jinjia(self, event: AstrMessageEvent,server: str = "", limit:str = "15"): - """ 金价 服务器""" - return await self.T2I_image_msg(event, lambda: self.jx3api.jinjia( self.serverdefault(server),limit)) - async def wujia(self, event: AstrMessageEvent,Name: str = "秃盒", server: str = ""): - """ 物价 外观名称""" - return await self.T2I_image_msg(event, lambda: self.jx3api.wujia(Name, self.serverdefault(server))) + + async def jiaoyihang(self, event: AstrMessageEvent,Name: str = "守缺式",server: str = ""): diff --git a/main.py b/main.py index 6e894e6..99ebafc 100644 --- a/main.py +++ b/main.py @@ -9,6 +9,7 @@ from astrbot.api import AstrBotConfig from .core.sqlite import AsyncSQLiteDB from .core.jx3api_data import JX3APIService +from .core.aijx3_data import AIJX3Service from .core.async_task import AsyncTask from .core.bilei_data import BiLeidata from .core.message import MessageBuilder @@ -85,7 +86,10 @@ class Jx3ApiPlugin(Star): if self.jx3api: await self.jx3api.close() - + + if self.aijx3: + await self.aijx3.close() + if self.local_sql_db: await self.local_sql_db.close() @@ -144,8 +148,9 @@ class Jx3ApiPlugin(Star): # 剑网三功能实例化 self.bilei = BiLeidata(self.local_sql_db) self.jx3api = JX3APIService(self.conf, self.plugin_sql_db, self.local_sql_db) + self.aijx3 = AIJX3Service(self.conf, self.plugin_sql_db, self.local_sql_db) self.jx3at = AsyncTask(cast(Context, self.context), self.conf, self.jx3api, self.local_sql_db) - self.jx3cmd = MessageBuilder(self.server, self.jx3api, self.bilei, self.jx3at, self.icons) + self.jx3cmd = MessageBuilder(self.server, self.jx3api, self.aijx3, self.bilei, self.jx3at, self.icons) async def init_bilei_data(self): @@ -233,6 +238,13 @@ class Jx3ApiPlugin(Star): "试炼排行": self. jx3cmd.shilianpaixing, "阵营拍卖": self. jx3cmd.zhengyingpaimai, "的卢": self. jx3cmd.dilujilu, + "金价": self. jx3cmd.jinjia, + "物价": self. jx3cmd.wujia, + "成本": self. jx3cmd.chengbeng, + "看号": self. jx3cmd.kanhao, + "帮战": self. jx3cmd.bangzhanjilu, + "沙盘": self. jx3cmd.shapan, + "诛恶": self. jx3cmd.zhueevent, "科举": self. jx3cmd.keju, @@ -255,17 +267,17 @@ class Jx3ApiPlugin(Star): "骚话": self. jx3cmd.shaohua, "资历": self. jx3cmd.zili, "解密": self. jx3cmd.jiemi, - "沙盘": self. jx3cmd.shapan, + "攻略": self. jx3cmd.qiyugonglue, "宏": self. jx3cmd.hong, "配装": self. jx3cmd.peizhuang, "百战": self. jx3cmd.baizhan, "扶摇": self. jx3cmd.fuyaojjiutian, - "诛恶": self. jx3cmd.zhueevent, + - "帮战记录": self. jx3cmd.bangzhanjilu, + "统战": self. jx3cmd.tongzhanyy, @@ -286,8 +298,8 @@ class Jx3ApiPlugin(Star): "所有名片": self. jx3cmd.shuoyoumingpian, "随机名片": self. jx3cmd.shuijimingpian, - "金价": self. jx3cmd.jinjia, - "物价": self. jx3cmd.wujia, + + "八卦": self. jx3cmd.bagua, "交易行": self. jx3cmd.jiaoyihang, "贴吧物价": self. jx3cmd.tiebawujia, diff --git a/templates/bangzhanjilu.html b/templates/bangzhanjilu.html index 2f3b08d..583b711 100644 --- a/templates/bangzhanjilu.html +++ b/templates/bangzhanjilu.html @@ -104,8 +104,6 @@ - - @@ -117,12 +115,10 @@ {% for item in items %} - - - - + + - + {% endfor %} diff --git a/templates/chengbeng.html b/templates/chengbeng.html new file mode 100644 index 0000000..7f51421 --- /dev/null +++ b/templates/chengbeng.html @@ -0,0 +1,1234 @@ + + + + + + +{{ name }} - 制作成本计算 + + + + + + +{# ========================================================== + 游戏币格式化宏 + + 接口价格单位按铜处理: + 100 铜 = 1 银 + 100 银 = 1 金 +========================================================== #} + +{% macro format_money(value) %} + {% set amount = value|default(0, true)|int %} + {% set gold = amount // 10000 %} + {% set silver = (amount % 10000) // 100 %} + {% set copper = amount % 100 %} + + + {% if gold > 0 %} + {{ gold }}金 + {% endif %} + + {% if silver > 0 or gold > 0 %} + {{ silver }}银 + {% endif %} + + {{ copper }}铜 + + + + {{ "{:,}".format(amount) }} 铜 + +{% endmacro %} + + +
+ + + + + + +
+ +
+ +
+
+ {{ name }} +
+
+ + +
+ +
+

{{ name }}

+ + + 品质 {{ quality }} + +
+ + + {% if tipInfo %} +
    + {% for tip in tipInfo %} +
  • {{ tip.text }}
  • + {% endfor %} +
+ {% endif %} + + +
+ +
+
使用等级
+
{{ level }} 级
+
+ +
+
技艺经验
+
+{{ exp }}
+
+ +
+
精力消耗
+
{{ costVigor }}
+
+ +
+
制作产出
+
+ {{ createItemMin }}~{{ createItemMax }} 个 +
+
+ +
+
物品编号
+
{{ createItemIndex }}
+
+ +
+ +
+ +
+ + + + +
+ +
+ +
+ 成品市场价格 + + + 样本 {{ price.sampleSize }} 条 + +
+ +
+ +
+
最低价格
+ +
+ {{ format_money(price.lowestPrice) }} +
+
+ +
+
平均价格
+ +
+ {{ format_money(price.avgPrice) }} +
+
+ +
+
最高价格
+ +
+ {{ format_money(price.highestPrice) }} +
+
+ +
+ + + +
+ + +
+ +
+ 制作材料总成本 + + + 共 {{ items|length }} 种材料 + +
+ +
+ +
+
最低采购成本
+ +
+ {{ format_money(total.lowestTotal) }} +
+
+ +
+
平均采购成本
+ +
+ {{ format_money(total.avgTotal) }} +
+
+ +
+
最高采购成本
+ +
+ {{ format_money(total.highestTotal) }} +
+
+ +
+ +
+ 接口成本小计 + + + {{ format_money(total.subtotal) }} + +
+ +
+ +
+ +
+ + + + +
+ +
+

合成所需物品

+ +
+ 交易行材料按市场行情计算,商店材料按固定单价计算 +
+
+ + +
+ + {% for item in items %} + +
+ +
+ +
+ {{ item.name }} +
+ + +
+ +

+ {{ item.name }} +

+ +
+ + {% if item.type == "trading" %} + + 交易行 + + {% elif item.type == "store" %} + + 商店购买 + + {% else %} + + {{ item.type }} + + {% endif %} + + + 品质 {{ item.quality }} + + + {% if item.genre is not none %} + + 分类 {{ item.genre }} + + {% endif %} + +
+ +
+ + +
+
需求数量
+ +
+ × {{ item.quantity }} +
+
+ +
+ + +
+ + {% if item.type == "trading" %} + +
+ +
+
+ 最低单价 +
+ +
+ {{ format_money(item.price.lowestPrice) }} +
+
+ +
+
+ 平均单价 +
+ +
+ {{ format_money(item.price.avgPrice) }} +
+
+ +
+
+ 最高单价 +
+ +
+ {{ format_money(item.price.highestPrice) }} +
+
+ +
+ + +
+ + 最低采购小计 + + + + {{ format_money( + item.price.lowestPrice * item.quantity + ) }} + +
+ + + + + + {% elif item.type == "store" %} + +
+ +
+
+ 商店单价 +
+ +
+ {{ format_money(item.price) }} +
+
+ +
+
+ 采购小计 +
+ +
+ {{ format_money( + item.price * item.quantity + ) }} +
+
+ +
+ + + {% else %} + +
+ + 暂无价格计算方式 + + + + - + +
+ + {% endif %} + +
+ +
+ + {% else %} + +
+ 暂无合成材料数据 +
+ + {% endfor %} + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/templates/wujia.html b/templates/wujia.html index 6b4f295..5601156 100644 --- a/templates/wujia.html +++ b/templates/wujia.html @@ -2,9 +2,15 @@ + + {{ name }} - 万宝楼行情 +{# + 先根据分组名称识别对应数据。 + + 查询区服不固定使用 list[3]: + 除电信区、双线区、无界区、公示期、出售期外, + 其他分组都视为查询区服。 + + 即使某个分组不存在,对应表格区域仍然会显示。 +#} + +{% set ns = namespace( + notice=none, + sale=none, + query=none, + telecom=none, + dual=none, + boundless=none +) %} + +{% for group in list %} + {% if group.name == "公示期" %} + {% set ns.notice = group %} + + {% elif group.name == "出售期" %} + {% set ns.sale = group %} + + {% elif group.name == "电信区" %} + {% set ns.telecom = group %} + + {% elif group.name == "双线区" %} + {% set ns.dual = group %} + + {% elif group.name == "无界区" %} + {% set ns.boundless = group %} + + {% elif ns.query is none %} + {% set ns.query = group %} + {% endif %} +{% endfor %} + +
-

{{ name }} ({{ alias }})

+

+ {{ name }} + {% if alias %} + ({{ alias }}) + {% endif %} +

- {{ name }} + {% if view %} + {{ name }} + {% endif %} + {% if desc %}

{{ desc }}

+ {% endif %}
+ 分类:{{ category }} 发售时间:{{ date }} - 参考价格:{{ cost }} 元 + 参考价格:{{ retail }} 元
- + +
万宝楼公示
-
区服服务器 宣战帮会 应战帮会 开始时间
{{ item.zoneName }}{{ item.serverName }}{{ item.declaringTongName }}{{ item.acceptingTongName }}{{ item.declaringName }}{{ item.acceptingName }} {{ item.startTime }}{{ item.matchDuration }}{{ item.durationSeconds }} {{ item.endTime }}
- - - - - - - - - - {% for item in list[3] %} - - - - - - - {% endfor %} - -
时间服务器价格状态
{{ item.date }}{{ item.server }}{{ item.value }}公示
+ +
+ + + + + + + + + + + + + {% if ns.notice and ns.notice.list %} + + {% for item in ns.notice.list %} + + + + + + + + + + + + {% endfor %} + + {% else %} + + + + + + {% endif %} + +
时间区服服务器价格状态
{{ item.date }}{{ item.zone }} + {{ item.server }} + + {{ item.value }} 元 + + 公示 +
+ 暂无公示数据 +
+
- + + +
万宝楼在售
- - - - - - - - - - - {% for item in list[4] %} - - - - - - - {% endfor %} - -
时间服务器价格状态
{{ item.date }}{{ item.server }}{{ item.value }}在售
+ +
+ + + + + + + + + + + + + {% if ns.sale and ns.sale.list %} + + {% for item in ns.sale.list %} + + + + + + + + + + + + {% endfor %} + + {% else %} + + + + + + {% endif %} + +
时间区服服务器价格状态
{{ item.date }}{{ item.zone }} + {{ item.server }} + + {{ item.value }} 元 + + 在售 +
+ 暂无在售数据 +
+
- -
-
查询区服
- - - - - - - - - - - {% for item in list[5] %} - - - - - - - {% endfor %} - -
时间服务器价格状态
{{ item.date }}{{ item.server }}{{ item.value }} - {% if item.source == 1 %}出售 - {% elif item.source == 2 %}收购 - {% elif item.source == 3 %}想出 - {% elif item.source == 4 %}想收 - {% elif item.source == 5 %}成交 - {% elif item.source == 6 %}正出 - {% else %}未知 - {% endif %} -
+ + + +
+
+ 查询区服 + {% if ns.query %} + :{{ ns.query.name }} + {% endif %} +
+ +
+ + + + + + + + + + + + {% if ns.query and ns.query.list %} + + {% for item in ns.query.list %} + + + + + + + + + + {% endfor %} + + {% else %} + + + + + + {% endif %} + +
时间服务器价格状态
{{ item.date }} + {{ item.server }} + + {{ item.value }} 元 + + {% if item.sale == 1 %} + 出售 + {% elif item.sale == 2 %} + 收购 + {% elif item.sale == 3 %} + 想出 + {% elif item.sale == 4 %} + 想收 + {% elif item.sale == 5 %} + 成交 + {% elif item.sale == 6 %} + 正出 + {% elif item.sale == 7 %} + 公示 + {% else %} + 未知 + {% endif %} +
+ 暂无查询区服数据 +
+
- + + +
电信区
- - - - - - - - - - - {% for item in list[0] %} - - - - - - - {% endfor %} - -
时间服务器价格状态
{{ item.date }}{{ item.server }}{{ item.value }} - {% if item.source == 1 %}出售 - {% elif item.source == 2 %}收购 - {% elif item.source == 3 %}想出 - {% elif item.source == 4 %}想收 - {% elif item.source == 5 %}成交 - {% elif item.source == 6 %}正出 - {% else %}未知 - {% endif %} -
+ +
+ + + + + + + + + + + + {% if ns.telecom and ns.telecom.list %} + + {% for item in ns.telecom.list %} + + + + + + + + + + {% endfor %} + + {% else %} + + + + + + {% endif %} + +
时间服务器价格状态
{{ item.date }} + {{ item.server }} + + {{ item.value }} 元 + + {% if item.sale == 1 %} + 出售 + {% elif item.sale == 2 %} + 收购 + {% elif item.sale == 3 %} + 想出 + {% elif item.sale == 4 %} + 想收 + {% elif item.sale == 5 %} + 成交 + {% elif item.sale == 6 %} + 正出 + {% elif item.sale == 7 %} + 公示 + {% else %} + 未知 + {% endif %} +
+ 暂无电信区数据 +
+
- + + +
双线区
- - - - - - - - - - - {% for item in list[1] %} - - - - - - - {% endfor %} - -
时间服务器价格状态
{{ item.date }}{{ item.server }}{{ item.value }} - {% if item.source == 1 %}出售 - {% elif item.source == 2 %}收购 - {% elif item.source == 3 %}想出 - {% elif item.source == 4 %}想收 - {% elif item.source == 5 %}成交 - {% elif item.source == 6 %}正出 - {% else %}未知 - {% endif %} -
+ +
+ + + + + + + + + + + + {% if ns.dual and ns.dual.list %} + + {% for item in ns.dual.list %} + + + + + + + + + + {% endfor %} + + {% else %} + + + + + + {% endif %} + +
时间服务器价格状态
{{ item.date }} + {{ item.server }} + + {{ item.value }} 元 + + {% if item.sale == 1 %} + 出售 + {% elif item.sale == 2 %} + 收购 + {% elif item.sale == 3 %} + 想出 + {% elif item.sale == 4 %} + 想收 + {% elif item.sale == 5 %} + 成交 + {% elif item.sale == 6 %} + 正出 + {% elif item.sale == 7 %} + 公示 + {% else %} + 未知 + {% endif %} +
+ 暂无双线区数据 +
+
- + + +
无界区
- - - - - - - - - - - {% for item in list[2] %} - - - - - - - {% endfor %} - -
时间服务器价格状态
{{ item.date }}{{ item.server }}{{ item.value }} - {% if item.source == 1 %}出售 - {% elif item.source == 2 %}收购 - {% elif item.source == 3 %}想出 - {% elif item.source == 4 %}想收 - {% elif item.source == 5 %}成交 - {% elif item.source == 6 %}正出 - {% else %}未知 - {% endif %} -
+ +
+ + + + + + + + + + + + {% if ns.boundless and ns.boundless.list %} + + {% for item in ns.boundless.list %} + + + + + + + + + + {% endfor %} + + {% else %} + + + + + + {% endif %} + +
时间服务器价格状态
{{ item.date }} + {{ item.server }} + + {{ item.value }} 元 + + {% if item.sale == 1 %} + 出售 + {% elif item.sale == 2 %} + 收购 + {% elif item.sale == 3 %} + 想出 + {% elif item.sale == 4 %} + 想收 + {% elif item.sale == 5 %} + 成交 + {% elif item.sale == 6 %} + 正出 + {% elif item.sale == 7 %} + 公示 + {% else %} + 未知 + {% endif %} +
+ 暂无无界区数据 +
+
@@ -335,4 +694,4 @@ - + \ No newline at end of file diff --git a/templates/zhueevent.html b/templates/zhueevent.html index 0df3790..8f2bf35 100644 --- a/templates/zhueevent.html +++ b/templates/zhueevent.html @@ -104,7 +104,7 @@ {% for item in items %} {{ item.server }} - {{ item.map_name }} + {{ item.mapName }} {{ item.time }} {% endfor %}