This commit is contained in:
qsc
2025-12-27 21:41:19 +08:00
parent 04ce36f017
commit 4bd6fc7c3e
5 changed files with 250 additions and 130 deletions
+38
View File
@@ -4,6 +4,8 @@ import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties from matplotlib.font_manager import FontProperties
from io import BytesIO from io import BytesIO
import base64 import base64
from datetime import datetime
import calendar
def load_template(template_name): def load_template(template_name):
""" """
@@ -165,3 +167,39 @@ def plot_line_chart_base64(data, x_field, y_field, title=None, reverse_x=False):
img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8') img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
return f"data:image/png;base64,{img_base64}" return f"data:image/png;base64,{img_base64}"
def build_calendar_items(start_date_str, data):
start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d").date()
weekday = start_date.weekday() # 周一0 ~ 周日6
weekday = (weekday + 1) % 7 # 调整:周日=0, 周一=1 ... 周六=6
result = []
row = []
# 第一行补空
for _ in range(weekday):
row.append({"date": "", "items": [], "is_today": False})
# 排数据
for i, day in enumerate(data):
# 识别今天
is_today = (day["date"] == start_date_str)
row.append({
"date": day["day"],
"items": [day],
"is_today": is_today,
})
if len(row) == 7:
result.append(row)
row = []
# 最后一行剩余补空
if row:
while len(row) < 7:
row.append({"date": "", "items": [], "is_today": False})
result.append(row)
return result
+10 -5
View File
@@ -7,7 +7,7 @@ from astrbot.api import AstrBotConfig
from .request import APIClient from .request import APIClient
from .aiosqlite import AsyncSQLite from .aiosqlite import AsyncSQLite
from .function_basic import load_template,flatten_field,extract_fields,gold_to_string from .function_basic import load_template,gold_to_string,build_calendar_items
class JX3Service: class JX3Service:
def __init__(self, api_config, config:AstrBotConfig): def __init__(self, api_config, config:AstrBotConfig):
@@ -159,19 +159,24 @@ class JX3Service:
data: Optional[Dict[str, Any]] = await self._base_request( data: Optional[Dict[str, Any]] = await self._base_request(
"jx3_richangyuche", "GET", params=params "jx3_richangyuche", "GET", params=params
) )
logger.info(f"richang 接口返回数据: {data}")
if not data: if not data:
return_data["msg"] = "获取接口信息失败" return_data["msg"] = "获取接口信息失败"
return return_data return return_data
# 3. 处理返回数据 # 3. 处理返回数据
try: try:
# 格式化字符串,利用字典的 get 方法提供默认值 return_data["data"]["items"] = build_calendar_items(data["today"]["date"],data["data"])
return_data["code"] = 0
except Exception as e: except Exception as e:
logger.error(f"richang 数据处理时出错: {e}") logger.error(f"richang 数据处理时出错: {e}")
return_data["msg"] = "处理接口返回信息时出错" return_data["msg"] = "处理接口返回信息时出错"
# 加载模板
try:
return_data["temp"] = load_template("richangyuche.html")
except FileNotFoundError as e:
logger.error(f"加载模板失败: {e}")
return_data["msg"] = "系统错误:模板文件不存在"
return_data["code"] = 200
return return_data return return_data
+3 -1
View File
@@ -154,8 +154,10 @@ class Jx3ApiPlugin(Star):
"""剑三 日常预测 服务器 """ """剑三 日常预测 服务器 """
try: try:
data= await self.jx3fun.richangyuche() data= await self.jx3fun.richangyuche()
logger.info(data)
if data["code"] == 200: if data["code"] == 200:
yield event.plain_result(data["data"]) url = await self.html_render(data["temp"], data["data"], options={})
yield event.image_result(url)
else: else:
yield event.plain_result(data["msg"]) yield event.plain_result(data["msg"])
return return
+93
View File
@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>未来战场日程表</title>
<style>
body {
margin: 0; padding: 20px;
background: #f5f7fb; color: #1f2333;
font-family: "Microsoft YaHei", Arial, sans-serif;
}
.calendar {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.calendar th {
background: #4f7cff;
color: white;
padding: 10px 0;
font-size: 18px;
}
.calendar td {
border: 1px solid #dce1eb;
vertical-align: top;
padding: 8px;
background: #ffffff;
}
.today {
background: #fff6d1;
border: 2px solid #ffb100;
}
.date-num {
font-weight: bold;
font-size: 16px;
margin-bottom: 4px;
display: block;
}
.item-block {
font-size: 12px;
margin-bottom: 6px;
padding: 4px;
border-radius: 4px;
background: #f0f3fa;
}
.item-block span {
font-weight: bold;
}
</style>
</head>
<body>
<h1 style="margin-bottom:20px;">未来战场日程表</h1>
<table class="calendar">
<thead>
<tr>
<th></th><th></th><th></th><th></th><th></th><th></th><th></th>
</tr>
</thead>
<tbody>
{% for week in items %}
<tr>
{% for day in week %}
{% if day.date %}
<td class="{% if day.is_today %}today{% endif %}">
<span class="date-num">{{ day.date }}</span>
{% for obj in day.items %}
<div class="item-block">
<div><span>战场:</span>{{ obj.battle }}</div>
<div><span>战役:</span>{{ obj.war }}</div>
<div><span>运车:</span>{{ obj.orecar }}</div>
<div><span>门派:</span>{{ obj.school }}</div>
<div><span>救援:</span>{{ obj.rescue }}</div>
{% if obj.card %}
<div><span>卡牌:</span>{{ obj.card | join('、') }}</div>
{% endif %}
</div>
{% endfor %}
</td>
{% else %}
<td style="background:#f0f2f7;"></td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
+105 -123
View File
@@ -1,145 +1,127 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>角色奇遇一览</title> <title>未来战场日历</title>
<style>
body {
margin: 0;
padding: 24px;
background: #f5f7fb;
color: #2c2c33;
font-family: "Microsoft YaHei", Arial, sans-serif;
}
.section { <style>
margin-bottom: 32px; body {
} font-family: "Microsoft YaHei", Arial, sans-serif;
background: #f1f2f6;
padding: 20px;
margin: 0;
}
.section-title { h1 {
font-size: 36px; text-align: center;
font-weight: bold; font-size: 32px;
margin-bottom: 16px; font-weight: 800;
border-left: 4px solid #4f7cff; margin-bottom: 25px;
padding-left: 10px; color: #222;
color: #1f2a44; }
}
.card-container { .calendar {
display: grid; width: 100%;
grid-template-columns: repeat(4, 1fr); max-width: 1200px;
gap: 16px; margin: 0 auto;
} border-collapse: collapse;
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
.card { .calendar th {
background: #ffffff; background: #d93939;
border-radius: 8px; color: white;
padding: 16px 12px; padding: 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08); font-size: 18px;
transition: transform 0.2s ease, box-shadow 0.2s ease; border: 1px solid #eee;
}
display: flex; .calendar td {
flex-direction: column; vertical-align: top;
align-items: center; padding: 6px;
justify-content: center; width: 14.2%;
text-align: center; border: 1px solid #eee;
min-height: 90px; min-height: 120px;
} background: #fff;
}
.card:hover { .date-label {
transform: translateY(-4px); font-size: 14px;
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.12); color: #666;
} font-weight: bold;
margin-bottom: 6px;
}
.event { .event-card {
font-size: 28px; background: #fff7f7;
font-weight: 600; border: 1px solid #f0dada;
margin-bottom: 6px; border-radius: 6px;
color: #2b3a67; padding: 6px;
} margin-top: 6px;
font-size: 14px;
line-height: 1.4em;
}
.time { .event-title {
font-size: 22px; font-weight: bold;
color: #7a7f99; color: #222;
} }
.empty { /* 鼠标悬停卡片高亮 */
color: #999; .event-card:hover {
font-size: 14px; background: #ffeaea;
padding: 10px 0; }
}
@media (max-width: 1000px) { /* 当日高亮,可选 */
.card-container { .today {
grid-template-columns: repeat(2, 1fr); background: #fef3c7;
} }
}
@media (max-width: 600px) { </style>
.card-container {
grid-template-columns: repeat(1, 1fr);
}
}
</style>
</head> </head>
<body> <body>
<!-- 普通奇遇 --> <h1>未来战场日历</h1>
<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">
<div class="event">{{ item.event }}</div>
<div class="time">{{ item.time }}</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty">暂无普通奇遇</div>
{% endif %}
</div>
<!-- 绝世奇遇 --> <table class="calendar">
<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">
<div class="event">{{ item.event }}</div>
<div class="time">{{ item.time }}</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty">暂无绝世奇遇</div>
{% endif %}
</div>
<!-- 宠物奇遇 --> <thead>
<div class="section"> <tr>
<div class="section-title"> <th>周日</th>
宠物奇遇({{ cwqy|length if cwqy else 0 }} <th>周一</th>
</div> <th>周二</th>
{% if cwqy %} <th>周三</th>
<div class="card-container"> <th>周四</th>
{% for item in cwqy %} <th>周五</th>
<div class="card"> <th>周六</th>
<div class="event">{{ item.event }}</div> </tr>
<div class="time">{{ item.time }}</div> </thead>
</div>
{% endfor %} <tbody>
</div>
{% else %} {% for week in calendar_rows %}
<div class="empty">暂无宠物奇遇</div> <tr>
{% endif %} {% for cell in week %}
</div> <td class="{% if cell.is_today %}today{% endif %}">
{% if cell.date %}
<div class="date-label">{{ cell.date }}</div>
{% for ev in cell.items %}
<div class="event-card">
<div class="event-title">{{ ev.war }}</div>
<div>{{ ev.battle }}</div>
</div>
{% endfor %}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</body> </body>
</html> </html>