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 %}
- | {{ item.zoneName }} |
- {{ item.serverName }} |
- {{ item.declaringTongName }} |
- {{ item.acceptingTongName }} |
+ {{ item.declaringName }} |
+ {{ item.acceptingName }} |
{{ item.startTime }} |
- {{ item.matchDuration }} |
+ {{ item.durationSeconds }} |
{{ item.endTime }} |
{% 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 }}
+
+
+ 品质 {{ quality }}
+
+
+
+
+ {% if tipInfo %}
+
+ {% for tip in tipInfo %}
+ - {{ tip.text }}
+ {% endfor %}
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
精力消耗
+
{{ 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 %}
+
+
+
+
+
+
+
+
+ {% 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 %}
+
-

+ {% if view %}
+

+ {% endif %}
+ {% if desc %}
{{ desc }}
+ {% endif %}
+ 分类:{{ category }}
发售时间:{{ date }}
- 参考价格:{{ cost }} 元
+ 参考价格:{{ retail }} 元
-
+
+
万宝楼公示
-
-
-
- | 时间 |
- 服务器 |
- 价格 |
- 状态 |
-
-
-
- {% for item in list[3] %}
-
- | {{ item.date }} |
- {{ item.server }} |
- {{ item.value }} |
- 公示 |
-
- {% endfor %}
-
-
+
+
-
+
+
+
万宝楼在售
-
-
-
- | 时间 |
- 服务器 |
- 价格 |
- 状态 |
-
-
-
- {% for item in list[4] %}
-
- | {{ item.date }} |
- {{ item.server }} |
- {{ item.value }} |
- 在售 |
-
- {% endfor %}
-
-
+
+
-
-
-
查询区服
-
-
-
- | 时间 |
- 服务器 |
- 价格 |
- 状态 |
-
-
-
- {% for item in list[5] %}
-
- | {{ 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 %}
- |
-
- {% endfor %}
-
-
+
+
+
+
+
+ 查询区服
+ {% if ns.query %}
+ :{{ ns.query.name }}
+ {% endif %}
+
+
+
-
+
+
+
电信区
-
-
-
- | 时间 |
- 服务器 |
- 价格 |
- 状态 |
-
-
-
- {% for item in list[0] %}
-
- | {{ 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 %}
- |
-
- {% endfor %}
-
-
+
+
-
+
+
+
双线区
-
-
-
- | 时间 |
- 服务器 |
- 价格 |
- 状态 |
-
-
-
- {% for item in list[1] %}
-
- | {{ 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 %}
- |
-
- {% endfor %}
-
-
+
+
-
+
+
+
无界区
-
-
-
- | 时间 |
- 服务器 |
- 价格 |
- 状态 |
-
-
-
- {% for item in list[2] %}
-
- | {{ 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 %}
- |
-
- {% endfor %}
-
-
+
+
@@ -335,4 +694,4 @@
-
+