Enhance abyss

Signed-off-by: Karako <karakohear@gmail.com>
Co-authored-by: 洛水居室 <luoshuijs@outlook.com>
Co-authored-by: xtaodada <xtao@xtaolink.cn>
This commit is contained in:
Karako 2022-10-12 17:34:55 +08:00 committed by GitHub
parent df8cc8bea2
commit 57edccd925
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 1550 additions and 426 deletions

View File

@ -1,6 +1,6 @@
import os import os
import time import time
from typing import Optional, Dict from typing import Dict, Optional
from jinja2 import Environment, PackageLoader, Template from jinja2 import Environment, PackageLoader, Template
from playwright.async_api import ViewportSize from playwright.async_api import ViewportSize
@ -65,7 +65,7 @@ class TemplateService:
viewport: ViewportSize = None, viewport: ViewportSize = None,
full_page: bool = True, full_page: bool = True,
evaluate: Optional[str] = None, evaluate: Optional[str] = None,
query_selector: str = None, query_selector: str = None
) -> bytes: ) -> bytes:
"""模板渲染成图片 """模板渲染成图片
:param template_path: 模板目录 :param template_path: 模板目录

View File

@ -19,6 +19,7 @@ __all__ = [
"ARTIFACT_DATA", "ARTIFACT_DATA",
"NAMECARD_DATA", "NAMECARD_DATA",
"honey_id_to_game_id", "honey_id_to_game_id",
"game_id_to_role_id",
"Data", "Data",
] ]
@ -91,3 +92,10 @@ NAMECARD_DATA: dict[str, dict[str, int | str]] = Data("namecard")
@functools.lru_cache() @functools.lru_cache()
def honey_id_to_game_id(honey_id: str, item_type: str) -> str | None: def honey_id_to_game_id(honey_id: str, item_type: str) -> str | None:
return next((key for key, value in HONEY_DATA[item_type].items() if value[0] == honey_id), None) return next((key for key, value in HONEY_DATA[item_type].items() if value[0] == honey_id), None)
@functools.lru_cache
def game_id_to_role_id(gid: str) -> int | None:
return next(
(int(key.split("-")[0]) for key, value in AVATAR_DATA.items() if value["icon"].split("_")[-1] == gid), None
)

View File

@ -217,6 +217,7 @@ roles = {
10000051: ["优菈", "Eula", "eula", "优拉", "尤拉", "尤菈", "浪花骑士", "记仇", "劳伦斯"], 10000051: ["优菈", "Eula", "eula", "优拉", "尤拉", "尤菈", "浪花骑士", "记仇", "劳伦斯"],
10000052: [ 10000052: [
"雷电将军", "雷电将军",
"Shougun",
"Raiden Shogun", "Raiden Shogun",
"Raiden", "Raiden",
"raiden", "raiden",

View File

@ -1,9 +1,17 @@
from typing import Dict, Optional """深渊数据查询"""
import asyncio
import re
from datetime import datetime
from functools import lru_cache, partial
from typing import List, Match, Optional, Tuple
import ujson as json
from arkowrapper import ArkoWrapper
from genshin import Client from genshin import Client
from telegram import Update from pytz import timezone
from telegram.constants import ChatAction from telegram import InlineKeyboardButton, InlineKeyboardMarkup, InputMediaPhoto, Update
from telegram.ext import CallbackContext, CommandHandler, MessageHandler, filters from telegram.constants import ChatAction, ParseMode
from telegram.ext import CallbackContext, filters
from core.base.assets import AssetsService from core.base.assets import AssetsService
from core.baseplugin import BasePlugin from core.baseplugin import BasePlugin
@ -13,23 +21,51 @@ from core.plugin import Plugin, handler
from core.template import TemplateService from core.template import TemplateService
from core.user import UserService from core.user import UserService
from core.user.error import UserNotFoundError from core.user.error import UserNotFoundError
from metadata.genshin import game_id_to_role_id
from utils.decorators.error import error_callable from utils.decorators.error import error_callable
from utils.decorators.restricts import restricts from utils.decorators.restricts import restricts
from utils.helpers import get_genshin_client, get_public_genshin_client from utils.helpers import async_re_sub, get_genshin_client, get_public_genshin_client
from utils.log import logger from utils.log import logger
TZ = timezone("Asia/Shanghai")
cmd_pattern = r"^/abyss\s*((?:\d+)|(?:all))?\s*(pre)?"
msg_pattern = r"^深渊数据((?:查询)|(?:总览))(上期)?\D?(\d*)?.*?$"
regex_01 = r"['\"]icon['\"]:\s*['\"](.*?)['\"]"
regex_02 = r"['\"]side_icon['\"]:\s*['\"](.*?)['\"]"
async def replace_01(match: Match, assets_service: AssetsService) -> str:
aid = game_id_to_role_id(re.findall(r"UI_AvatarIcon_(.*?).png", match.group(1))[0])
return (await assets_service.avatar(aid).icon()).as_uri()
async def replace_02(match: Match, assets_service: AssetsService) -> str:
aid = game_id_to_role_id(re.findall(r"UI_AvatarIcon_Side_(.*?).png", match.group(1))[0])
return (await assets_service.avatar(aid).side()).as_uri()
@lru_cache
def get_args(text: str) -> Tuple[int, bool, bool]:
if text.startswith("/"):
result = re.match(cmd_pattern, text).groups()
try:
floor = int(result[0] or 0)
except ValueError:
floor = 0
return floor, result[0] == "all", bool(result[1])
else:
result = re.match(msg_pattern, text).groups()
return int(result[2] or 0), result[0] == "总览", result[1] == "上期"
class AbyssUnlocked(Exception): class AbyssUnlocked(Exception):
"""根本没动""" """根本没动"""
pass
class NoMostKills(Exception): class NoMostKills(Exception):
"""挑战了但是数据没刷新""" """挑战了但是数据没刷新"""
pass
class Abyss(Plugin, BasePlugin): class Abyss(Plugin, BasePlugin):
"""深渊数据查询""" """深渊数据查询"""
@ -46,95 +82,245 @@ class Abyss(Plugin, BasePlugin):
self.user_service = user_service self.user_service = user_service
self.assets_service = assets_service self.assets_service = assets_service
@staticmethod @handler.command("abyss", block=False)
def _get_role_star_bg(value: int): @handler.message(filters.Regex(msg_pattern), block=False)
if value == 4:
return "./background/roleStarBg4.png"
elif value == 5:
return "./background/roleStarBg5.png"
else:
raise ValueError("错误的数据")
async def _get_abyss_data(self, client: Client, uid: Optional[int] = None) -> Dict:
if uid is None:
_uid = client.uid
await client.get_record_cards()
else:
_uid = uid
spiral_abyss_info = await client.get_spiral_abyss(_uid)
if not spiral_abyss_info.unlocked:
raise AbyssUnlocked
ranks = spiral_abyss_info.ranks
if len(spiral_abyss_info.ranks.most_kills) == 0:
raise NoMostKills
abyss_data = {
"uid": _uid,
"max_floor": spiral_abyss_info.max_floor,
"total_battles": spiral_abyss_info.total_battles,
"total_stars": spiral_abyss_info.total_stars,
"most_played_list": [],
"most_kills": {
"icon": await self.assets_service.avatar(ranks.most_kills[0].id).side(),
"value": ranks.most_kills[0].value,
},
"strongest_strike": {
"icon": await self.assets_service.avatar(ranks.strongest_strike[0].id).side(),
"value": ranks.strongest_strike[0].value,
},
"most_damage_taken": {
"icon": await self.assets_service.avatar(ranks.most_damage_taken[0].id).side(),
"value": ranks.most_damage_taken[0].value,
},
"most_bursts_used": {
"icon": await self.assets_service.avatar(ranks.most_bursts_used[0].id).side(),
"value": ranks.most_bursts_used[0].value,
},
"most_skills_used": {
"icon": await self.assets_service.avatar(ranks.most_skills_used[0].id).side(),
"value": ranks.most_skills_used[0].value,
},
}
# most_kills
most_played_list = ranks.most_played
for most_played in most_played_list:
temp = {
"icon": await self.assets_service.avatar(most_played.id).icon(),
"value": most_played.value,
"background": self._get_role_star_bg(most_played.rarity),
}
abyss_data["most_played_list"].append(temp)
return abyss_data
@handler(CommandHandler, command="abyss", block=False)
@handler(MessageHandler, filters=filters.Regex("^深渊数据查询(.*)"), block=False)
@restricts() @restricts()
@error_callable @error_callable
async def command_start(self, update: Update, context: CallbackContext) -> None: async def command_start(self, update: Update, context: CallbackContext) -> None:
user = update.effective_user user = update.effective_user
message = update.effective_message message = update.effective_message
logger.info(f"用户 {user.full_name}[{user.id}] 查深渊挑战命令请求")
await message.reply_chat_action(ChatAction.TYPING) # 若查询帮助
try: if (message.text.startswith("/") and "help" in message.text) or "帮助" in message.text:
try: await message.reply_text(
client = await get_genshin_client(user.id) "<b>深渊挑战数据</b>功能使用帮助(中括号表示可选参数)\n\n"
abyss_data = await self._get_abyss_data(client) "指令格式:\n<code>/abyss + [层数/all] + [pre]</code>\n<code>pre</code>表示上期)\n\n"
except CookiesNotFoundError: "文本格式:\n<code>深渊数据 + 查询/总览 + [上期] + [层数]</code> \n\n"
client, uid = await get_public_genshin_client(user.id) "例如以下指令都正确:\n"
abyss_data = await self._get_abyss_data(client, uid) "<code>/abyss</code>\n<code>/abyss 12 pre</code>\n<code>/abyss all pre</code>\n"
except UserNotFoundError: "<code>深渊数据查询</code>\n<code>深渊数据查询上期第12层</code>\n<code>深渊数据总览上期</code>",
reply_message = await message.reply_text("未查询到账号信息,请先私聊派蒙绑定账号") parse_mode=ParseMode.HTML,
)
logger.info(f"用户 {user.full_name}[{user.id}] 查询[bold]深渊挑战数据[/bold]帮助", extra={"markup": True})
return
# 解析参数
floor, total, previous = get_args(message.text)
if floor > 12 or floor < 0:
reply_msg = await message.reply_text("深渊层数输入错误,请重新输入")
if filters.ChatType.GROUPS.filter(message): if filters.ChatType.GROUPS.filter(message):
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 10) self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 10)
self._add_delete_message_job(context, message.chat_id, message.message_id, 10) self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
return return
except TooManyRequestPublicCookies: elif 0 < floor < 9:
await message.reply_text("用户查询次数过多 请稍后重试") previous = False
return
except (AbyssUnlocked, NoMostKills): logger.info(
await message.reply_text("本次深渊旅行者还没挑战呢,咕咕咕~~~") f"用户 {user.full_name}[{user.id}] [bold]深渊挑战数据[/bold]请求: "
return f"floor={floor} total={total} previous={previous}",
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO) extra={"markup": True},
png_data = await self.template_service.render(
"genshin/abyss", "abyss.html", abyss_data, {"width": 865, "height": 504}, full_page=False
) )
await message.reply_photo(png_data, filename=f"abyss_{user.id}.png", allow_sending_without_reply=True)
try:
client = await get_genshin_client(user.id)
await client.get_record_cards()
uid = client.uid
except UserNotFoundError: # 若未找到账号
if filters.ChatType.GROUPS.filter(message):
buttons = [[InlineKeyboardButton("点我私聊", url=f"https://t.me/{context.bot.username}?start=set_cookies")]]
reply_msg = await message.reply_text(
"未查询到您所绑定的账号信息,请先私聊派蒙绑定账号", reply_markup=InlineKeyboardMarkup(buttons)
)
self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 30)
self._add_delete_message_job(context, message.chat_id, message.message_id, 30)
else:
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
return
except CookiesNotFoundError: # 若未找到cookie
client, uid = await get_public_genshin_client(user.id)
except TooManyRequestPublicCookies:
reply_msg = await message.reply_text(
"查询次数太多,请您稍后重试",
)
if filters.ChatType.GROUPS.filter(message):
self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 10)
self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
return
async def reply_message(content: str) -> None:
_user = await client.get_genshin_user(uid)
_reply_msg = await message.reply_text(
f"旅行者 {_user.info.nickname}(<code>{uid}</code>) {content}", parse_mode=ParseMode.HTML
)
if filters.ChatType.GROUPS.filter(message):
self._add_delete_message_job(context, _reply_msg.chat_id, _reply_msg.message_id, 10)
self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
if total:
reply_msg = await message.reply_text("派蒙需要时间整理深渊数据,还请耐心等待哦~")
if filters.ChatType.GROUPS.filter(message):
self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 10)
self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
await message.reply_chat_action(ChatAction.TYPING)
try:
images = await self.get_rendered_pic(client, uid, floor, total, previous)
except AbyssUnlocked: # 若深渊未解锁
return await reply_message("还未解锁深渊哦~")
except NoMostKills: # 若深渊还未挑战
return await reply_message("还没有挑战本次深渊呢,咕咕咕~")
except IndexError: # 若深渊为挑战此层
return await reply_message("还没有挑战本层呢,咕咕咕~")
if images is None:
return await reply_message(f"还没有第 {floor} 层的挑战数据")
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
for group in ArkoWrapper(images).map(InputMediaPhoto).group(10): # 每 10 张图片分一个组
await message.reply_media_group(list(group), allow_sending_without_reply=True)
logger.info(f"用户 {user.full_name}[{user.id}] [bold]深渊挑战数据[/bold]: 成功发送图片", extra={"markup": True})
async def get_rendered_pic(
self, client: Client, uid: int, floor: int, total: bool, previous: bool
) -> Optional[List[bytes]]:
"""
获取渲染后的图片
Args:
client (Client): 获取 genshin 数据的 client
uid (int): 需要查询的 uid
floor (int): 层数
total (bool): 是否为总览
previous (bool): 是否为上期
Returns:
bytes格式的图片
"""
def json_encoder(value):
if isinstance(value, datetime):
return value.astimezone(TZ).strftime("%Y-%m-%d %H:%M:%S")
return value
abyss_data = await client.get_spiral_abyss(uid, previous=previous, lang="zh-cn")
if not abyss_data.unlocked:
raise AbyssUnlocked()
if not abyss_data.ranks.most_kills:
raise NoMostKills()
end_time = abyss_data.end_time.astimezone(TZ)
time = end_time.strftime("%Y年%m月") + "" if end_time.day <= 16 else "" + ""
stars = [i.stars for i in filter(lambda x: x.floor > 8, abyss_data.floors)]
total_stars = f"{sum(stars)} ({'-'.join(map(str, stars))})"
render_data = {}
result = await async_re_sub(
regex_01,
partial(replace_01, assets_service=self.assets_service),
abyss_data.json(encoder=json_encoder),
)
result = await async_re_sub(regex_02, partial(replace_02, assets_service=self.assets_service), result)
render_data["time"] = time
render_data["stars"] = total_stars
render_data["uid"] = uid
render_data["floor_colors"] = {
1: "#374952",
2: "#374952",
3: "#55464B",
4: "#55464B",
5: "#55464B",
6: "#1D2A5D",
7: "#1D2A5D",
8: "#1D2A5D",
9: "#292B58",
10: "#382024",
11: "#252550",
12: "#1D2A4A",
}
if total:
avatars = await client.get_genshin_characters(uid, lang="zh-cn")
render_data["avatar_data"] = {i.id: i.constellation for i in avatars}
data = json.loads(result)
render_data["data"] = data
render_result = []
async def overview_task():
render_result.append(
[
-1,
await self.template_service.render(
"genshin/abyss", "overview.html", render_data, viewport={"width": 750, "height": 580}
),
]
)
async def floor_task(floor_index: int):
floor_d = data["floors"][floor_index]
render_result.append(
[
floor_d["floor"],
await self.template_service.render(
"genshin/abyss",
"floor.html",
{
**render_data,
"floor": floor_d,
"total_stars": f"{floor_d['stars']}/{floor_d['max_stars']}",
},
viewport={"width": 690, "height": 500},
full_page=True,
),
]
)
task_list = [asyncio.create_task(overview_task())]
for i, f in enumerate(data["floors"]):
if f["floor"] >= 9:
task_list.append(asyncio.create_task(floor_task(i)))
await asyncio.gather(*task_list)
return list(map(lambda x: x[1], sorted(render_result, key=lambda x: x[0])))
elif floor < 1:
render_data["data"] = json.loads(result)
return [
await self.template_service.render(
"genshin/abyss",
"overview.html",
render_data,
viewport={"width": 750, "height": 580},
)
]
else:
num_dic = {
"0": "",
"1": "",
"2": "",
"3": "",
"4": "",
"5": "",
"6": "",
"7": "",
"8": "",
"9": "",
}
if num := num_dic.get(str(floor)):
render_data["floor-num"] = num
else:
render_data["floor-num"] = f"{num_dic.get(str(floor % 10))}"
floors = json.loads(result)["floors"]
if (floor_data := list(filter(lambda x: x["floor"] == floor, floors))) is None:
return None
avatars = await client.get_genshin_characters(uid, lang="zh-cn")
render_data["avatar_data"] = {i.id: i.constellation for i in avatars}
render_data["floor"] = floor_data[0]
render_data["total_stars"] = f"{floor_data[0]['stars']}/{floor_data[0]['max_stars']}"
return [
await self.template_service.render(
"genshin/abyss", "floor.html", render_data, viewport={"width": 690, "height": 500}, full_page=True
)
]

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,101 +0,0 @@
<!DOCTYPE html>
<html lang="zh-ch">
<head>
<meta charset="UTF-8">
<title>abyss</title>
<link type="text/css" href="../../styles/tailwind.min.css" rel="stylesheet">
<link type="text/css" href="../../styles/public.css" rel="stylesheet">
<style>
#container {
width: 865px;
height: 504px;
background: url("./background/lookback-bg.png");
background-size: cover;
}
.character-icon {
width: 128px;
height: 128px;
}
.character-side-icon {
position: absolute;
right: 0;
bottom: 1px;
width: 48px;
height: 48px;
}
div:has(> img.character-side-icon) {
position: relative;
height: 32px;
}
div:has(> img.character-side-icon) > div {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
</style>
</head>
<body>
<div class="mx-auto flex flex-col h-full bg-no-repeat bg-cover" id="container">
<div class="title text-2xl my-4 text-yellow-500 mx-auto">深境螺旋</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-white bg-opacity-10">
<div class="uid text-center mx-auto">UID {{ uid }}</div>
<div class="text-center mx-auto">最深抵达 {{ max_floor }}</div>
<div class="text-center mx-auto">战斗次数 {{ total_battles }}</div>
<div class="text-center mx-auto">获得星级 {{ total_stars }}</div>
</div>
<div class="base-info flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">出战次数</div>
<div class="mx-auto flex my-2">
{% for most_played in most_played_list %}
<div class="rounded-lg mx-2 overflow-hidden" style="background-color: rgb(233, 229, 220)">
<div class="character-icon rounded-br-3xl bg-cover overflow-hidden"
style="background: url({{ most_played.background }});background-size: cover;">
<img src="{{ most_played.icon }}" alt=""></div>
<div class="text-center">{{ most_played.value }}次</div>
</div>
{% endfor %}
</div>
</div>
<div class="flex flex-col my-1">
<div class="flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">战斗数据榜</div>
</div>
<div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最多击破数:{{ most_kills.value }}</div>
<img class="character-side-icon ml-auto" src="{{ most_kills.icon }}" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最强一击:{{ strongest_strike.value }}</div>
<img class="character-side-icon ml-auto" src="{{ strongest_strike.icon }}" alt="">
</div>
</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">承受最多伤害:{{ most_damage_taken.value }}</div>
<img class="character-side-icon ml-auto" src="{{ most_damage_taken.icon }}" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素爆发数:{{ most_bursts_used.value }}</div>
<img class="character-side-icon ml-auto" src="{{ most_bursts_used.icon }}" alt="">
</div>
</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素战技释放次数:{{ most_skills_used.value }}</div>
<img class="character-side-icon ml-auto" src="{{ most_skills_used.icon }}" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6"></div>
</div>
</div>
</div>
<div class="my-2"></div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -2,115 +2,518 @@
<html lang="zh-ch"> <html lang="zh-ch">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>abyss</title> <title>abyss-example</title>
<script src="https://cdn.tailwindcss.com"></script> <link type="text/css" href="./style.css" rel="stylesheet"/>
<style> <link type="text/css" href="../../styles/public.css" rel="stylesheet"/>
#container {
width: 865px;
height: 504px;
background: url("./background/lookback-bg.png");
background-size: cover;
}
.character-icon {
width: 128px;
height: 128px;
}
.character-side-icon {
position: absolute;
right: 0;
bottom: 1px;
width: 48px;
height: 48px;
}
div:has(> img.character-side-icon) {
position: relative;
height: 32px;
}
div:has(> img.character-side-icon) > div {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
</style>
</head> </head>
<body> <body>
<div class="mx-auto flex flex-col h-full bg-no-repeat bg-cover" id="container"> <div class="container">
<div class="title text-2xl my-4 text-yellow-500 mx-auto">深境螺旋</div> <div class="overview">
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-white bg-opacity-10"> <div class="title">挑战回顾</div>
<div class="uid text-center mx-auto">UID 1414514</div> <div class="summarize">
<div class="text-center mx-auto">最深抵达 12-3</div> <div>
<div class="text-center mx-auto">战斗次数 12</div> <div>UID: 100206192</div>
<div class="text-center mx-auto">获得星级 36</div> <div class="star">
<span>36 (9-9-9-9)</span>
</div> </div>
<div class="base-info flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">出战次数</div>
<div class="mx-auto flex my-2">
<div class="bg-white rounded-lg mx-2 overflow-hidden">
<div class="character-icon rounded-br-3xl bg-cover"
style="background: url('./background/roleStarBg4.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
<div class="bg-white rounded-lg mx-2 overflow-hidden">
<div class="character-icon rounded-br-3xl bg-cover"
style="background: url('./background/roleStarBg4.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
<div class="bg-white rounded-lg mx-2 overflow-hidden">
<div class="character-icon rounded-br-3xl bg-cover"
style="background: url('./background/roleStarBg5.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
<div class="bg-white rounded-lg mx-2 overflow-hidden">
<div class="character-icon rounded-br-3xl bg-cover"
style="background: url('./background/roleStarBg5.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
</div>
</div>
<div class="flex flex-col my-1">
<div class="flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">战斗数据榜</div>
</div> </div>
<div> <div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 "> <div>时间: 2022年10月上</div>
<div class="text-center flex flex-row flex-1 mr-6"> <div>最深抵达: 12-3</div>
<div class="my-auto">最多击破数21</div>
<img class="character-side-icon" src="./../../img/example/256x256.png" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最强一击21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div> </div>
</div> </div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white"> <div class="most-played">
<div class="text-center flex flex-row flex-1 mr-6"> <div class="caption">出战次数</div>
<div class="my-auto">承受最多伤害21</div> <div class="characters">
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt=""> <div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
<div class="text-center flex flex-row flex-1 mr-6"> <div class="caption">15次</div>
<div class="my-auto">元素爆发数21</div> </div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt=""> <i class="four-star"></i>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">15次</div>
</div>
<i class="four-star"></i>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">15次</div>
</div>
<i class="four-star"></i>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">15次</div>
</div>
</div>
</div>
<div>
<div class="caption">战斗数据</div>
<div class="ranks">
<div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank">战斗次数: 12</div>
<div class="rank">
<span>最多击破999</span>
<img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/>
</div>
</div>
<div>
<div class="rank">
<span>最强一击: 999,999</span>
<img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/>
</div>
<div class="rank">
<span>最多承伤: 114,514</span>
<img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/>
</div>
</div>
<div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank">
<span>元素爆发: 26</span>
<img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/>
</div>
<div class="rank">
<span>元素战技: 48</span>
<img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/>
</div>
</div>
</div>
</div>
</div>
<div class="floors">
<div class="floor" style="background-image: url('./background/floor1.png');background-color: #374952;">
<div class="head">
<div class="floor-name">
<div class="floor-num"></div>
<div>深境螺旋第一层</div>
</div>
<div class="star">
<span>9/9</span>
</div>
</div>
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 1 间 <span style="color: #A3A3A3">2022-10-01 10:02:05</span>
</div>
<div class="stars">
<div class="star"></div>
<div class="star dim-star"></div>
<div class="star dim-star"></div>
</div>
</div>
<div class="battles">
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">5命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--green)">4命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--green)">3命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">上半</div>
</div>
<div class="battle">
<div class="character">
<div style="background-color: var(--blue)">2命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--blue)">1命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">下半</div>
</div>
</div>
</div>
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 2 间 <span style="color: #A3A3A3">2022-10-01 10:02:05</span>
</div>
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
</div>
<div class="battles">
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">上半</div>
</div>
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">下半</div>
</div>
</div>
</div>
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 3 间 <span style="color: #A3A3A3">2022-10-01 10:02:05</span>
</div>
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star dim-star"></div>
</div>
</div>
<div class="battles">
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--green)">4命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--blue)">2命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
</div>
</div>
</div>
</div>
<div class="floor" style="background-image: url('./background/floor1.png');background-color: #374952;">
<div class="head">
<div class="floor-name">
<div class="floor-num">
<div>1</div>
</div>
<span>深境螺旋第一层</span>
</div>
<div class="star">
<span>9/9</span>
</div>
</div>
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 1 间 <span style="color: #A3A3A3">2022-10-01 10:02:05</span>
</div>
<div class="stars">
<div class="star"></div>
<div class="star dim-star"></div>
<div class="star dim-star"></div>
</div>
</div>
<div class="battles">
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">5命</div>
<div class="element" style="background-image: url('../../img/element/Cyro.png')"></div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--green)">4命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--green)">3命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">上半</div>
</div>
<div class="battle">
<div class="character">
<div style="background-color: var(--blue)">2命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--blue)">1命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">下半</div>
</div>
</div>
</div>
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 2 间 <span style="color: #A3A3A3">2022-10-01 10:02:05</span>
</div>
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
</div>
<div class="battles">
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">上半</div>
</div>
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="battle-info">下半</div>
</div>
</div>
</div>
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 3 间 <span style="color: #A3A3A3">2022-10-01 10:02:05</span>
</div>
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star dim-star"></div>
</div>
</div>
<div class="battles">
<div class="battle">
<div class="character">
<div style="background-color: var(--red)">6命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--green)">4命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div style="background-color: var(--blue)">2命</div>
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div>
<div class="character">
<div class="icon" style="background-image: url('../../background/rarity/half/5.png')">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div>
<div class="caption">Lv.90</div>
</div> </div>
</div> </div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素战技释放次数21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div> </div>
<div class="text-center flex flex-row flex-1 mr-6"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="my-2"></div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>floor</title>
<link type="text/css" href="./style.css" rel="stylesheet"/>
<link type="text/css" href="../../styles/public.css" rel="stylesheet"/>
<style>
body {
margin: 0;
padding: 0;
}
.floors, .floor {
border-radius: unset;
margin: 0;
}
.floor-num > div:last-child {
display: flex;
flex-flow: column;
justify-content: center;
align-content: center;
}
</style>
</head>
<body>
<div class="container">
<div class="floors">
<div
class="floor"
style="
background-image: url('./background/floor{{ floor.floor }}.png');
background-color: {{ floor_colors[floor.floor] }};"
>
<div class="head">
<div class="floor-name">
<div class="floor-num"></div>
<div>
<div>UID: {{ uid }}</div>
<div>深境螺旋第 {{ floor.floor }} 层</div>
</div>
</div>
<div class="star">
<span>{{ total_stars }}</span>
</div>
</div>
{% for chamber in floor.chambers %}
<div class="hr"></div>
<div class="chamber">
<div class="chamber-info">
<div>
第 {{ loop.index }} 间 <span
style="color: #A3A3A3">{{ chamber.battles[0].timestamp }}</span>
</div>
<div class="stars">
{% for n in range(chamber.stars) %}
<div class="star"></div>
{% endfor %}
{% for n in range(chamber.max_stars - chamber.stars) %}
<div class="star dim-star"></div>
{% endfor %}
</div>
</div>
<div class="battles">
{% for battle in chamber.battles %}
<div class="battle">
{% for character in battle.characters %}
<div class="character">
{% if avatar_data[character.id] > 0 %}
{% set constellation = avatar_data[character.id] %}
{% set bg = ['blue','blue', 'green','green', 'red', 'red'][constellation - 1] %}
<div style="background-color: var(--{{ bg }})">
{{ constellation }} 命
</div>
{% endif %}
<div class="icon"
style="background-image: url('../../background/rarity/half/{{ character.rarity }}.png')">
<img src="{{ character.icon }}" alt=""/>
</div>
<div class="caption">Lv.{{ character.level }}</div>
</div>
{% endfor %}
{% if loop.length > 1 %}
<div class="battle-info">{{ ['上', '下'][loop.index0] }}半</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html lang="zh-ch">
<head>
<meta charset="UTF-8">
<title>overview</title>
<link type="text/css" href="./style.css" rel="stylesheet"/>
<link type="text/css" href="../../styles/public.css" rel="stylesheet"/>
<style>
body {
margin: 0;
padding: 0;
}
.overview {
border-radius: unset;
}
</style>
</head>
<body>
<div class="container">
<div class="overview">
<div class="title">挑战回顾</div>
<div class="summarize">
<div>
<div>UID: {{ uid }}</div>
<div class="star">
<span>{{ stars }}</span>
</div>
</div>
<div>
<div>时间: {{ time }}</div>
<div>最深抵达: {{ data.max_floor }}</div>
</div>
</div>
<div class="most-played">
<div class="caption">出战次数</div>
<div class="characters">
{% for avatar in data.ranks.most_played %}
<div class="character">
<div
class="icon"
style="background-image: url('../../background/rarity/half/{{ avatar.rarity }}.png')"
>
<img src="{{ avatar.icon }}" alt=""/>
</div>
<div class="caption">{{ avatar.value }} 次</div>
</div>
{% if loop.index != 4 %}
<i class="four-star"></i>
{% endif %}
{% endfor %}
</div>
</div>
<div>
<div class="caption">战斗数据</div>
<div class="ranks">
<div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank">战斗次数: {{ data.total_battles }}</div>
<div class="rank">
<span>最多击破:{{ data.ranks.most_kills[0].value }}</span>
<img src="{{ data.ranks.most_kills[0].side_icon }}" alt=""/>
</div>
</div>
<div>
<div class="rank">
<span>最强一击: {{ data.ranks.strongest_strike[0].value }}</span>
<img src="{{ data.ranks.strongest_strike[0].side_icon }}" alt=""/>
</div>
<div class="rank">
<span>最多承伤: {{ data.ranks.most_damage_taken[0].value }}</span>
<img src="{{ data.ranks.most_damage_taken[0].side_icon }}" alt=""/>
</div>
</div>
<div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank">
<span>元素爆发: {{ data.ranks.most_bursts_used[0].value }}</span>
<img src="{{ data.ranks.most_bursts_used[0].side_icon }}" alt=""/>
</div>
<div class="rank">
<span>元素战技: {{ data.ranks.most_skills_used[0].value }}</span>
<img src="{{ data.ranks.most_skills_used[0].side_icon }}" alt=""/>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,346 @@
:root {
--white: rgb(246 248 249);
--bg-color: rgb(233 229 220);
--h-color: rgb(203 189 162);
--red: rgb(255 86 33/ 80%);
--blue: rgb(98 168 233/ 80%);
--green: rgb(67 185 124/ 80%);
}
body {
margin: 0;
padding: 10px;
}
.hr {
width: 100%;
height: 3px;
background-color: rgb(246 248 249 / 50%);
}
.container {
width: 750px;
position: relative;
filter: drop-shadow(2px 2px 5px rgb(0 0 0 /70%));
}
.title {
text-align: center;
font-size: 27px;
font-weight: bold;
color: var(--h-color);
}
.caption {
margin: 10px 0;
color: var(--h-color);
font-size: 20px;
}
/* 概览 */
.overview {
height: 540px;
padding: 20px 40px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-image: linear-gradient(to top, rgb(0 0 0 / 10%), rgb(0 0 0 / 10%)), url("./background/lookback-bg.png");
background-attachment: local;
border-radius: 15px;
overflow: hidden;
}
.summarize {
font-size: 20px;
width: calc(100% - 90px);
height: calc(100px - 20px);
margin: 20px 0;
padding: 10px 0 10px 80px;
border-radius: 5px;
border: 2px solid rgb(118 121 120 / 80%);
outline: 4px solid rgb(74, 82, 101);
background-color: rgb(74 82 101 / 60%);
background-image: url("./background/banner 01.png"), url("./background/banner 02.png");
background-repeat: no-repeat, no-repeat;
background-position: right, left;
background-size: auto 100%, auto 100%;
backdrop-filter: blur(5px);
}
.summarize > div {
width: 100%;
height: 50%;
color: var(--white);
display: flex;
align-items: center;
}
.summarize > div > div {
flex: 1;
}
.star {
display: inline-flex;
align-items: center;
position: relative;
}
.star::before {
content: "";
width: 40px;
height: 40px;
background-size: cover;
background-image: url("./background/star.png");
}
.star > span {
margin-left: 10px;
}
.most-played {
width: 100%;
margin: 30px 0;
}
.characters {
width: calc(100% - 60px);
padding: 0 30px;
display: flex;
justify-content: center;
align-items: center;
}
.character {
width: 100px;
height: 125px;
margin: 0 20px;
background-color: rgb(233 229 220);
overflow: hidden;
border-radius: 10px;
position: relative;
}
.icon {
width: 100%;
height: 100px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
overflow: hidden;
border-radius: 0 0 20px 0;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: center;
justify-content: space-around;
}
.icon > img {
width: inherit;
height: inherit;
}
.character > .caption {
font-size: 18px;
margin: 4px 0 0;
padding: 0;
height: min-content;
text-align: center;
color: black;
}
.four-star {
width: 15px;
height: 15px;
position: relative;
}
.four-star::after {
content: '';
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: inherit;
height: inherit;
background-position: center;
background-image: url("./background/four-star.png");
background-blend-mode: lighten;
background-size: contain;
}
.ranks {
width: calc(100% + 80px);
transform: translateX(-40px);
color: var(--white);
position: relative;
display: flex;
flex-flow: column;
flex-wrap: wrap;
}
.ranks > div {
font-size: 18px;
width: 100%;
height: 43px;
display: flex;
align-items: center;
}
.rank {
flex: 1;
position: relative;
display: flex;
margin-left: 80px;
margin-right: 60px;
}
.ranks > div > .rank:first-child {
margin-right: 10px;
}
.rank > img {
width: 50px;
position: absolute;
right: 0;
bottom: -5px;
}
/* 层数 */
.floors {
margin-top: 20px;
}
.floor {
margin: 20px 0;
padding: 0 30px;
width: calc(100% - 60px);
border-radius: 20px;
overflow: hidden;
outline: rgb(233 229 220 / 30%) solid 3px;
outline-offset: -7px;
background-position: top center;
background-repeat: no-repeat;
background-size: contain;
}
.head {
width: 100%;
height: 160px;
display: flex;
}
.floor-name {
font-size: 28px;
display: flex;
align-items: center;
font-weight: bold;
color: var(--white);
}
.floor-name > div:not(.floor-num) {
margin-left: 20px;
text-shadow: 1px 1px 5px rgb(0 0 0/50%);
}
.floor-num {
color: black;
width: 100px;
height: 100px;
background-image: url("./background/abyss.png");
background-size: contain;
filter: drop-shadow(0 0 5px rgb(0 0 0/80%)) grayscale(10%);
position: relative;
}
.head > .star {
margin-left: auto;
float: right;
color: var(--white);
font-size: 25px;
text-shadow: 1px 1px 5px rgb(0 0 0/50%);
}
.head > .star::before {
width: 50px;
height: 50px;
}
.chamber {
margin: 10px 0;
display: flex;
flex-flow: column;
}
.chamber-info {
height: 70px;
display: flex;
align-items: center;
color: var(--white);
font-size: 22px;
}
.stars {
margin-left: auto;
}
.dim-star::before {
filter: brightness(50%);
}
.battle {
margin: 10px 0 20px 0;
display: flex;
justify-content: center;
align-items: center;
}
.battle > .character {
flex: 2;
max-width: 120px;
height: 145px;
}
.battle > .battle-info {
flex: 1;
color: var(--white);
font-size: 22px;
font-weight: bold;
}
.battle > .character > div:first-child:not(.icon, .element) {
position: absolute;
top: 0;
right: 0;
padding: 5px;
min-width: 27px;
text-align: center;
border-radius: 0 0 0 10px;
filter: drop-shadow(1px 1px 5px rgb(0 0 0/50%));
font-weight: 500;
color: var(--white);
}
.battle > .character > .element {
position: absolute;
top: 3px;
left: 3px;
width: 30px;
height: 30px;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.battle > .character > .icon {
width: 100%;
height: fit-content;
border-radius: 0 0 28px 0;
}
.battle > .character > .caption {
font-size: 20px;
margin-top: 2px;
}

View File

@ -31,12 +31,12 @@
{% for material in area.materials %} {% for material in area.materials %}
<div class="material"> <div class="material">
<div class="material-icon" <div class="material-icon"
style="background-image: url(./bg/rarity/half/{{ material.rarity }}.png)"> style="background-image: url(../../background/rarity/half/{{ material.rarity }}.png)">
<img alt="{{ material.name }}" src="{{ material.icon }}"/> <img alt="{{ material.name }}" src="{{ material.icon }}"/>
</div> </div>
<div class="material-star"> <div class="material-star">
{% for _ in range(material.rarity) %} {% for _ in range(material.rarity) %}
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
@ -53,7 +53,7 @@
{% endif %} {% endif %}
> >
<div class="item-icon" <div class="item-icon"
style="background-image: url(./bg/rarity/full/{{ item.rarity }}.png)"> style="background-image: url(../../background/rarity/full/{{ item.rarity }}.png)">
{% if item.level != none %} {% if item.level != none %}
<div>Lv.{{ item.level }}</div> <div>Lv.{{ item.level }}</div>
{% endif %} {% endif %}

View File

@ -27,52 +27,52 @@
</span> </span>
<span class="materials"> <span class="materials">
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/2.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/2.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/3.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/3.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/4.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/4.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/5.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/5.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
</span> </span>
</div> </div>
<div class="area-content"> <div class="area-content">
<div class="item character item-not-owned"> <div class="item character item-not-owned">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div> <div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div>
<img src="../../assets/avatar/10000058/icon.png" alt="八重神子"/> <img src="../../assets/avatar/10000058/icon.png" alt="八重神子"/>
@ -82,7 +82,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div> <div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div>
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
@ -92,7 +92,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div> <div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div>
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
@ -102,7 +102,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
@ -111,7 +111,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
<div class="item-name"> <div class="item-name">
@ -119,7 +119,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
<div class="item-name"> <div class="item-name">
@ -139,52 +139,52 @@
</span> </span>
<span class="materials"> <span class="materials">
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/2.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/2.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/3.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/3.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/4.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/4.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/5.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/5.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
</span> </span>
</div> </div>
<div class="area-content"> <div class="area-content">
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div> <div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div>
<img src="../../assets/avatar/10000058/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000058/icon.png" alt="神里绫华"/>
@ -194,7 +194,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div> <div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div>
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
@ -204,7 +204,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div> <div style="background-color: rgba(255, 20, 147, 0.8); backdrop-filter: blur(3px);">6命</div>
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
@ -214,7 +214,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
@ -223,7 +223,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
<div class="item-name"> <div class="item-name">
@ -231,7 +231,7 @@
</div> </div>
</div> </div>
<div class="item character"> <div class="item character">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/icon.png" alt="神里绫华"/>
</div> </div>
<div class="item-name"> <div class="item-name">
@ -255,45 +255,45 @@
</span> </span>
<span class="materials"> <span class="materials">
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/2.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/2.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/3.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/3.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/4.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/4.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
<div class="material-icon" style="background-image: url(./bg/rarity/half/5.png)"> <div class="material-icon" style="background-image: url(../../background/rarity/half/5.png)">
<img alt="" src="../../assets/material/114003/icon.png"/> <img alt="" src="../../assets/material/114003/icon.png"/>
</div> </div>
<div class="material-star"> <div class="material-star">
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
</div> </div>
</div> </div>
</span> </span>
@ -303,7 +303,7 @@
<div class="role"> <div class="role">
<img src="../../assets/avatar/10000063/side.png" alt="申鹤"/> <img src="../../assets/avatar/10000063/side.png" alt="申鹤"/>
</div> </div>
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: deepskyblue">精炼5</div> <div style="background-color: deepskyblue">精炼5</div>
<img src="../../assets/weapon/14501/awaken.png" alt="天空之刃"/> <img src="../../assets/weapon/14501/awaken.png" alt="天空之刃"/>
@ -316,7 +316,7 @@
<div class="role"> <div class="role">
<img src="../../assets/avatar/10000041/side.png" alt="神里绫华"/> <img src="../../assets/avatar/10000041/side.png" alt="神里绫华"/>
</div> </div>
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: deepskyblue">精炼5</div> <div style="background-color: deepskyblue">精炼5</div>
<img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/> <img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/>
@ -329,7 +329,7 @@
<div class="role"> <div class="role">
<img src="../../assets/avatar/10000067/side.png" alt="神里绫华"/> <img src="../../assets/avatar/10000067/side.png" alt="神里绫华"/>
</div> </div>
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: deepskyblue">精炼5</div> <div style="background-color: deepskyblue">精炼5</div>
<img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/> <img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/>
@ -342,7 +342,7 @@
<div class="role"> <div class="role">
<img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/> <img src="../../assets/avatar/10000002/side.png" alt="神里绫华"/>
</div> </div>
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<div>Lv.90</div> <div>Lv.90</div>
<div style="background-color: deepskyblue">精炼5</div> <div style="background-color: deepskyblue">精炼5</div>
<img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/> <img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/>
@ -352,7 +352,7 @@
</div> </div>
</div> </div>
<div class="item weapon"> <div class="item weapon">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/> <img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/>
</div> </div>
<div class="item-name"> <div class="item-name">
@ -360,7 +360,7 @@
</div> </div>
</div> </div>
<div class="item weapon"> <div class="item weapon">
<div class="item-icon" style="background-image: url(./bg/rarity/full/5.png)"> <div class="item-icon" style="background-image: url(../../background/rarity/full/5.png)">
<img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/> <img src="../../assets/weapon/14502/awaken.png" alt="天空之刃"/>
</div> </div>
<div class="item-name"> <div class="item-name">

View File

@ -1,13 +1,13 @@
@font-face { @font-face {
font-family: 'HYWH'; font-family: 'HYWH';
src: url('../../fonts/汉仪文黑-85W.ttf') format('truetype'); src: url('../../fonts/HYWenHei-85W.ttf') format('truetype');
} }
:root { :root {
--bg-color: #ebe5d9; --bg-color: #EBE5D9;
--font-color: #514e49; --font-color: #514E49;
--color-1: #d6ba92; --color-1: #D6BA92;
--shadow: #726c65; --shadow: #726C65;
} }
@ -190,7 +190,7 @@ body {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
filter: drop-shadow(1px 1px 2px #6c6c6c); filter: drop-shadow(1px 1px 2px #6C6C6C);
} }
.material-star > img { .material-star > img {

View File

@ -31,12 +31,12 @@
{% for material in area.materials %} {% for material in area.materials %}
<div class="material"> <div class="material">
<div class="material-icon" <div class="material-icon"
style="background-image: url(./bg/rarity/half/{{ material.rarity }}.png)"> style="background-image: url(../../background/rarity/half/{{ material.rarity }}.png)">
<img alt="{{ material.name }}" src="{{ material.icon }}"/> <img alt="{{ material.name }}" src="{{ material.icon }}"/>
</div> </div>
<div class="material-star"> <div class="material-star">
{% for _ in range(material.rarity) %} {% for _ in range(material.rarity) %}
<img alt="star" src="./bg/rarity/star.webp"/> <img alt="star" src="../../background/rarity/star.webp"/>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
@ -58,7 +58,7 @@
</div> </div>
{% endif %} {% endif %}
<div class="item-icon" <div class="item-icon"
style="background-image: url(./bg/rarity/full/{{ item.rarity }}.png)"> style="background-image: url(../../background/rarity/full/{{ item.rarity }}.png)">
{% if item.level != none %} {% if item.level != none %}
<div>Lv.{{ item.level }}</div> <div>Lv.{{ item.level }}</div>
{% endif %} {% endif %}

View File

@ -4,7 +4,7 @@
<meta http-equiv="content-type" content="text/html;charset=utf-8"/> <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<link rel="shortcut icon" href="#"/> <link rel="shortcut icon" href="#"/>
<link rel="stylesheet" type="text/css" href="gacha_count.css"/> <link rel="stylesheet" type="text/css" href="gacha_count.css"/>
<link rel="preload" href="./../../fonts/汉仪文黑-85W.ttf" as="font"> <link rel="preload" href="../../fonts/HYWenHei-85W.ttf" as="font">
<link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font"> <link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font">
<link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image"> <link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image">
<link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image"> <link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image">

View File

@ -7,7 +7,7 @@
@font-face { @font-face {
font-family: "HYWenHei-55W"; font-family: "HYWenHei-55W";
src: url("./../../fonts/汉仪文黑-85W.ttf"); src: url("../../fonts/HYWenHei-85W.ttf");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -22,7 +22,7 @@
body { body {
font-size: 16px; font-size: 16px;
width: 530px; width: 530px;
color: #1e1f20; color: #1E1F20;
transform: scale(1.5); transform: scale(1.5);
transform-origin: 0 0; transform-origin: 0 0;
} }
@ -30,7 +30,7 @@ body {
.container { .container {
width: 530px; width: 530px;
padding: 20px 15px 10px 15px; padding: 20px 15px 10px 15px;
background-color: #f5f6fb; background-color: #F5F6FB;
} }
.head_box { .head_box {
@ -72,7 +72,7 @@ body {
margin-top: 20px; margin-top: 20px;
margin-bottom: 20px; margin-bottom: 20px;
padding: 10px 5px 5px 5px; padding: 10px 5px 5px 5px;
background: #fff; background: #FFF;
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%); box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
position: relative; position: relative;
} }
@ -111,7 +111,7 @@ body {
box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%); box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%);
height: 70px; height: 70px;
width: 70px; width: 70px;
background: #e9e5dc; background: #E9E5DC;
position: relative; position: relative;
} }
@ -132,7 +132,7 @@ body {
z-index: 9; z-index: 9;
font-size: 18px; font-size: 18px;
text-align: center; text-align: center;
color: #fff; color: #FFF;
border-radius: 3px; border-radius: 3px;
padding: 1px 5px; padding: 1px 5px;
background: rgb(0 0 0 / 50%); background: rgb(0 0 0 / 50%);
@ -144,15 +144,15 @@ body {
} }
.label_302 { .label_302 {
background-color: #e69449; background-color: #E69449;
} }
.label_200 { .label_200 {
background-color: #757cc8; background-color: #757CC8;
} }
.label { .label {
color: #fff; color: #FFF;
border-radius: 10px; border-radius: 10px;
font-size: 16px; font-size: 16px;
padding: 2px 7px; padding: 2px 7px;
@ -177,38 +177,38 @@ body {
} }
.list_box .item .life1 { .list_box .item .life1 {
background-color: #62a8ea; background-color: #62A8EA;
} }
.list_box .item .life2 { .list_box .item .life2 {
background-color: #62a8ea; background-color: #62A8EA;
} }
.list_box .item .life3 { .list_box .item .life3 {
background-color: #45b97c; background-color: #45B97C;
} }
.list_box .item .life4 { .list_box .item .life4 {
background-color: #45b97c; background-color: #45B97C;
} }
.list_box .item .life5 { .list_box .item .life5 {
background-color: #ff5722; background-color: #FF5722;
} }
.list_box .item .life6 { .list_box .item .life6 {
background-color: #ff5722; background-color: #FF5722;
} }
.logo { .logo {
font-size: 14px; font-size: 14px;
font-family: "tttgbnumber", serif; font-family: "tttgbnumber", serif;
text-align: center; text-align: center;
color: #7994a7; color: #7994A7;
} }
.hasMore { .hasMore {
font-size: 12px; font-size: 12px;
margin: -6px 0 10px 6px; margin: -6px 0 10px 6px;
color: #7f858a; color: #7F858A;
} }

View File

@ -4,7 +4,7 @@
<meta http-equiv="content-type" content="text/html;charset=utf-8"/> <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<link rel="shortcut icon" href="#"/> <link rel="shortcut icon" href="#"/>
<link rel="stylesheet" type="text/css" href="gacha_count.css"/> <link rel="stylesheet" type="text/css" href="gacha_count.css"/>
<link rel="preload" href="./../../fonts/汉仪文黑-85W.ttf" as="font"> <link rel="preload" href="../../fonts/HYWenHei-85W.ttf" as="font">
<link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font"> <link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font">
<link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image"> <link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image">
<link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image"> <link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image">

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -6,12 +6,54 @@
} }
@font-face { @font-face {
font-family: "hywh"; font-family: "HYWH";
src: url("../fonts/汉仪文黑-85W.ttf"); src: url("../fonts/HYWenHei-35W.ttf") format("truetype");
font-weight: 200;
font-style: normal;
}
@font-face {
font-family: "HYWH";
src: url("../fonts/HYWenHei-45W.ttf") format("truetype");
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: "HYWH";
src: url("../fonts/HYWenHei-55W.ttf") format("truetype");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: "HYWH";
src: url("../fonts/HYWenHei-65W.ttf") format("truetype");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "HYWH";
src: url("../fonts/HYWenHei-75W.ttf") format("truetype");
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: "HYWH";
src: url("../fonts/HYWenHei-85W.ttf") format("truetype");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: "Number";
src: url("../fonts/tttgbnumber.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
body { body {
font-family: "hywh", "seguiemj", emoji, system-ui; font-family: "Number", "HYWH", "seguiemj", emoji, serif, system-ui;
} }

View File

@ -1,9 +1,13 @@
from __future__ import annotations
import hashlib import hashlib
import os import os
import re
from asyncio import create_subprocess_shell from asyncio import create_subprocess_shell
from asyncio.subprocess import PIPE from asyncio.subprocess import PIPE
from inspect import iscoroutinefunction
from pathlib import Path from pathlib import Path
from typing import Optional, Tuple, TypeVar, Union, cast from typing import Awaitable, Callable, Match, Optional, Pattern, Tuple, TypeVar, Union, cast
import aiofiles import aiofiles
import genshin import genshin
@ -80,10 +84,7 @@ async def url_to_file(url: str, return_path: bool = False) -> str:
await f.write(data.content) await f.write(data.content)
logger.debug(f"url_to_file 获取url[{url}] 并下载到 file_dir[{file_dir}]") logger.debug(f"url_to_file 获取url[{url}] 并下载到 file_dir[{file_dir}]")
if return_path: return file_dir if return_path else Path(file_dir).as_uri()
return file_dir
return Path(file_dir).as_uri()
async def get_genshin_client(user_id: int, region: Optional[RegionEnum] = None, need_cookie: bool = True) -> Client: async def get_genshin_client(user_id: int, region: Optional[RegionEnum] = None, need_cookie: bool = True) -> Client:
@ -133,9 +134,7 @@ async def get_public_genshin_client(user_id: int) -> Tuple[Client, Optional[int]
def region_server(uid: Union[int, str]) -> RegionEnum: def region_server(uid: Union[int, str]) -> RegionEnum:
if isinstance(uid, int): if isinstance(uid, (int, str)):
region = REGION_MAP.get(str(uid)[0])
elif isinstance(uid, str):
region = REGION_MAP.get(str(uid)[0]) region = REGION_MAP.get(str(uid)[0])
else: else:
raise TypeError("UID variable type error") raise TypeError("UID variable type error")
@ -161,3 +160,50 @@ async def execute(command, pass_error=True):
except UnicodeDecodeError: except UnicodeDecodeError:
result = str(stdout.decode("gbk").strip()) result = str(stdout.decode("gbk").strip())
return result return result
async def async_re_sub(
pattern: str | Pattern,
repl: str | Callable[[Match], str] | Callable[[Match], Awaitable[str]],
string: str,
count: int = 0,
flags: int = 0,
) -> str:
"""
一个支持 repl 参数为 async 函数的 re.sub
Args:
pattern (str | Pattern): 正则对象
repl (str | Callable[[Match], str] | Callable[[Match], Awaitable[str]]): 替换后的文本或函数
string (str): 目标文本
count (int): 要替换的最大次数
flags (int): 标志常量
Returns:
返回经替换后的字符串
"""
result = ""
temp = string
if count != 0:
for _ in range(count):
match = re.search(pattern, temp, flags=flags)
replaced = None
if iscoroutinefunction(repl):
# noinspection PyUnresolvedReferences,PyCallingNonCallable
replaced = await repl(match)
elif callable(repl):
# noinspection PyCallingNonCallable
replaced = repl(match)
result += temp[: match.span(1)[0]] + (replaced or repl)
temp = temp[match.span(1)[1] :]
else:
while match := re.search(pattern, temp, flags=flags):
replaced = None
if iscoroutinefunction(repl):
# noinspection PyUnresolvedReferences,PyCallingNonCallable
replaced = await repl(match)
elif callable(repl):
# noinspection PyCallingNonCallable
replaced = repl(match)
result += temp[: match.span(1)[0]] + (replaced or repl)
temp = temp[match.span(1)[1] :]
return result + temp

View File

@ -77,7 +77,14 @@ log_console = Console(color_system=color_system, theme=Theme(DEFAULT_STYLE), wid
class Traceback(BaseTraceback): class Traceback(BaseTraceback):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs.update({"show_locals": True, "max_frames": config.logger.traceback_max_frames}) kwargs.update(
{
"show_locals": True,
"max_frames": config.logger.traceback_max_frames,
"locals_max_length": 3,
"locals_max_string": 80,
}
)
super(Traceback, self).__init__(*args, **kwargs) super(Traceback, self).__init__(*args, **kwargs)
self.theme = PygmentsSyntaxTheme(MonokaiProStyle) self.theme = PygmentsSyntaxTheme(MonokaiProStyle)