✨ Support zzz agent detail
2
pdm.lock
@ -2212,7 +2212,7 @@ name = "simnet"
|
||||
version = "0.1.22"
|
||||
requires_python = "<4.0,>=3.8"
|
||||
git = "https://github.com/PaiGramTeam/SIMNet"
|
||||
revision = "9839a06bb87403443ac2cbea0ffde4156b05d902"
|
||||
revision = "ed7c061d82af4fe8c5a07f0d10c568b5e467662b"
|
||||
summary = "Modern API wrapper for Genshin Impact & Honkai: Star Rail built on asyncio and pydantic."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
|
@ -26,6 +26,7 @@ class SetCommandPlugin(Plugin):
|
||||
BotCommand("signal_log_import", "导入调频记录"),
|
||||
BotCommand("signal_log_export", "导出调频记录"),
|
||||
BotCommand("signal_log_delete", "删除调频记录"),
|
||||
BotCommand("agent_detail", "角色详细信息"),
|
||||
# Cookie 查询类
|
||||
BotCommand("sign", "米游社绝区零每日签到"),
|
||||
BotCommand("dailynote_tasks", "自动便笺提醒"),
|
||||
|
350
plugins/zzz/agent_detail.py
Normal file
@ -0,0 +1,350 @@
|
||||
import math
|
||||
from typing import TYPE_CHECKING, List, Tuple, Optional, Union
|
||||
|
||||
from simnet.models.zzz.calculator import ZZZCalculatorCharacterDetails, ZZZCalculatorAvatarProperty
|
||||
from telegram import (
|
||||
InlineKeyboardButton,
|
||||
InlineKeyboardMarkup,
|
||||
)
|
||||
from telegram.constants import ChatAction
|
||||
from telegram.ext import filters
|
||||
|
||||
from core.config import config
|
||||
from core.dependence.redisdb import RedisDB
|
||||
from core.plugin import Plugin, handler
|
||||
from core.services.template.services import TemplateService
|
||||
from metadata.shortname import roleToName, idToRole
|
||||
from plugins.tools.genshin import GenshinHelper
|
||||
from utils.log import logger
|
||||
from utils.uid import mask_number
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from simnet import ZZZClient
|
||||
from telegram import Update
|
||||
from telegram.ext import ContextTypes
|
||||
from core.services.template.models import RenderResult
|
||||
|
||||
__all__ = ("AgentDetailPlugin",)
|
||||
|
||||
|
||||
class ZZZCalculatorAvatarPropertyModify(ZZZCalculatorAvatarProperty):
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
return {
|
||||
"生命值": "hp",
|
||||
"攻击力": "atk",
|
||||
"防御力": "def",
|
||||
"冲击力": "impact",
|
||||
"暴击率": "crit-rate",
|
||||
"暴击伤害": "crit-dmg",
|
||||
"异常掌控": "anomaly-proficiency",
|
||||
"异常精通": "anomaly-mastery",
|
||||
"穿透率": "pen-ratio",
|
||||
"能量自动回复": "energy-regen",
|
||||
}.get(self.property_name, "")
|
||||
|
||||
|
||||
color_map = {
|
||||
"1011": "#c8e16c",
|
||||
"1021": "#a0351c",
|
||||
"1031": "#e6adaa",
|
||||
"1041": "#febb2e",
|
||||
"1061": "#c8d7bd",
|
||||
"1081": "#af3e3a",
|
||||
"1101": "#de643d",
|
||||
"1111": "#ddc374",
|
||||
"1121": "#a68d73",
|
||||
"1131": "#28bdcc",
|
||||
"1141": "#d0d3e0",
|
||||
"1151": "#e8cda2",
|
||||
"1181": "#b75339",
|
||||
"1191": "#c9becc",
|
||||
"1211": "#c4c1b1",
|
||||
"1241": "#4e7ebd",
|
||||
"1281": "#e9d892",
|
||||
}
|
||||
|
||||
|
||||
class NeedClient(Exception):
|
||||
"""无缓存,需要 StarRailClient"""
|
||||
|
||||
|
||||
class AgentDetailPlugin(Plugin.Conversation):
|
||||
"""角色详细信息查询"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
helper: GenshinHelper,
|
||||
template_service: TemplateService,
|
||||
redis: RedisDB,
|
||||
):
|
||||
self.template_service = template_service
|
||||
self.helper = helper
|
||||
self.qname = "plugins:agent_detail"
|
||||
self.redis = redis.client
|
||||
self.expire = 15 * 60 # 15分钟
|
||||
self.kitsune: Optional[str] = None
|
||||
|
||||
async def set_characters_for_redis(
|
||||
self,
|
||||
uid: int,
|
||||
nickname: str,
|
||||
data: "ZZZCalculatorCharacterDetails",
|
||||
) -> None:
|
||||
data_k = f"{self.qname}:{uid}:data"
|
||||
json_data = data.json(by_alias=True)
|
||||
await self.redis.set(data_k, json_data, ex=self.expire)
|
||||
|
||||
async def del_characters_for_redis(
|
||||
self,
|
||||
uid: int,
|
||||
) -> None:
|
||||
data_k = f"{self.qname}:{uid}:data"
|
||||
await self.redis.delete(data_k)
|
||||
|
||||
async def get_characters_for_redis(
|
||||
self,
|
||||
uid: int,
|
||||
) -> Tuple[Optional[str], Optional["ZZZCalculatorCharacterDetails"]]:
|
||||
data_k = f"{self.qname}:{uid}:data"
|
||||
data_v = await self.redis.get(data_k)
|
||||
if data_v is None:
|
||||
return None, None
|
||||
json_data = str(data_v, encoding="utf-8")
|
||||
return "", ZZZCalculatorCharacterDetails.parse_raw(json_data)
|
||||
|
||||
async def get_characters(
|
||||
self, uid: int, client: "ZZZClient" = None
|
||||
) -> Tuple[Optional[str], Optional["ZZZCalculatorCharacterDetails"]]:
|
||||
nickname, data = await self.get_characters_for_redis(uid)
|
||||
if nickname is None or data is None:
|
||||
if not client:
|
||||
raise NeedClient
|
||||
data1 = await client.get_zzz_characters()
|
||||
cids = [i.id for i in data1.characters]
|
||||
data = await client.get_zzz_character_info(cids)
|
||||
await self.set_characters_for_redis(client.player_id, "", data)
|
||||
return nickname, data
|
||||
|
||||
def parse_render_data(self, data: "ZZZCalculatorCharacterDetails", nickname: str, ch_id: int, uid: int):
|
||||
char = None
|
||||
for i in data.characters:
|
||||
if i.id == ch_id:
|
||||
char = i
|
||||
break
|
||||
props = [ZZZCalculatorAvatarPropertyModify(**i.dict()) for i in char.properties]
|
||||
return {
|
||||
"uid": mask_number(uid),
|
||||
"char": char,
|
||||
"props": props,
|
||||
"color": color_map.get(str(char.id), "#010101"),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def gen_button(
|
||||
data: "ZZZCalculatorCharacterDetails",
|
||||
user_id: Union[str, int],
|
||||
uid: int,
|
||||
page: int = 1,
|
||||
) -> List[List[InlineKeyboardButton]]:
|
||||
"""生成按钮"""
|
||||
buttons = []
|
||||
|
||||
if data.characters:
|
||||
buttons = [
|
||||
InlineKeyboardButton(
|
||||
idToRole(value.id),
|
||||
callback_data=f"get_role_detail|{user_id}|{uid}|{idToRole(value.id)}",
|
||||
)
|
||||
for value in data.characters
|
||||
if value.id
|
||||
]
|
||||
all_buttons = [buttons[i : i + 4] for i in range(0, len(buttons), 4)]
|
||||
send_buttons = all_buttons[(page - 1) * 3 : page * 3]
|
||||
last_page = page - 1 if page > 1 else 0
|
||||
all_page = math.ceil(len(all_buttons) / 3)
|
||||
next_page = page + 1 if page < all_page and all_page > 1 else 0
|
||||
last_button = []
|
||||
if last_page:
|
||||
last_button.append(
|
||||
InlineKeyboardButton(
|
||||
"<< 上一页",
|
||||
callback_data=f"get_role_detail|{user_id}|{uid}|{last_page}",
|
||||
)
|
||||
)
|
||||
if last_page or next_page:
|
||||
last_button.append(
|
||||
InlineKeyboardButton(
|
||||
f"{page}/{all_page}",
|
||||
callback_data=f"get_role_detail|{user_id}|{uid}|empty_data",
|
||||
)
|
||||
)
|
||||
if next_page:
|
||||
last_button.append(
|
||||
InlineKeyboardButton(
|
||||
"下一页 >>",
|
||||
callback_data=f"get_role_detail|{user_id}|{uid}|{next_page}",
|
||||
)
|
||||
)
|
||||
if last_button:
|
||||
send_buttons.append(last_button)
|
||||
return send_buttons
|
||||
|
||||
async def get_render_result(
|
||||
self, data: "ZZZCalculatorCharacterDetails", nickname: str, ch_id: int, uid: int
|
||||
) -> "RenderResult":
|
||||
final = self.parse_render_data(data, nickname, ch_id, uid)
|
||||
return await self.template_service.render(
|
||||
"zzz/agent_detail/agent_detail.html",
|
||||
final,
|
||||
{"width": 1024, "height": 1200},
|
||||
query_selector=".shareContainer_2ZR-xeyd",
|
||||
full_page=True,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_caption(data: "ZZZCalculatorCharacterDetails", character_id: int) -> str:
|
||||
tags = []
|
||||
for character in data.characters:
|
||||
if character.id == character_id:
|
||||
tags.append(character.name)
|
||||
tags.append(f"等级{character.level}")
|
||||
tags.append(f"命座{character.rank}")
|
||||
if weapon := character.weapon:
|
||||
tags.append(weapon.name)
|
||||
tags.append(f"武器等级{weapon.level}")
|
||||
tags.append(f"精{weapon.star}")
|
||||
break
|
||||
return "#" + " #".join(tags)
|
||||
|
||||
@handler.command(command="agent_detail", block=False)
|
||||
@handler.message(filters=filters.Regex("^角色详细信息查询(.*)"), block=False)
|
||||
async def command_start(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None:
|
||||
user_id = await self.get_real_user_id(update)
|
||||
message = update.effective_message
|
||||
uid, offset = self.get_real_uid_or_offset(update)
|
||||
args = self.get_args(context)
|
||||
ch_name = None
|
||||
for i in args:
|
||||
if i.startswith("@"):
|
||||
continue
|
||||
ch_name = roleToName(i)
|
||||
if ch_name:
|
||||
break
|
||||
self.log_user(
|
||||
update,
|
||||
logger.info,
|
||||
"角色详细信息查询命令请求 || character_name[%s]",
|
||||
ch_name,
|
||||
)
|
||||
await message.reply_chat_action(ChatAction.TYPING)
|
||||
async with self.helper.genshin(user_id, player_id=uid, offset=offset) as client:
|
||||
nickname, data = await self.get_characters(client.player_id, client)
|
||||
uid = client.player_id
|
||||
if ch_name is None:
|
||||
buttons = self.gen_button(data, user_id, uid)
|
||||
if isinstance(self.kitsune, str):
|
||||
photo = self.kitsune
|
||||
else:
|
||||
photo = open("resources/img/aaa.jpg", "rb")
|
||||
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
|
||||
reply_message = await message.reply_photo(
|
||||
photo=photo,
|
||||
caption=f"请选择你要查询的角色 - UID {uid}",
|
||||
reply_markup=InlineKeyboardMarkup(buttons),
|
||||
)
|
||||
if reply_message.photo:
|
||||
self.kitsune = reply_message.photo[-1].file_id
|
||||
return
|
||||
for characters in data.characters:
|
||||
if idToRole(characters.id) == ch_name:
|
||||
break
|
||||
else:
|
||||
await message.reply_text(f"未在游戏中找到 {ch_name} ,请检查角色是否存在,或者等待角色数据更新后重试")
|
||||
return
|
||||
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
|
||||
render_result = await self.get_render_result(data, nickname, characters.id, client.player_id)
|
||||
await render_result.reply_photo(
|
||||
message,
|
||||
filename=f"{client.player_id}.png",
|
||||
reply_markup=self.get_custom_button(user_id, uid, characters.id),
|
||||
caption=self.get_caption(data, characters.id),
|
||||
)
|
||||
|
||||
@handler.callback_query(pattern=r"^get_role_detail\|", block=False)
|
||||
async def get_role_detail(self, update: "Update", _: "ContextTypes.DEFAULT_TYPE") -> None:
|
||||
callback_query = update.callback_query
|
||||
user = callback_query.from_user
|
||||
message = callback_query.message
|
||||
|
||||
async def get_role_detail_callback(
|
||||
callback_query_data: str,
|
||||
) -> Tuple[str, int, int]:
|
||||
_data = callback_query_data.split("|")
|
||||
_user_id = int(_data[1])
|
||||
_uid = int(_data[2])
|
||||
_result = _data[3]
|
||||
logger.debug(
|
||||
"callback_query_data函数返回 result[%s] user_id[%s] uid[%s]",
|
||||
_result,
|
||||
_user_id,
|
||||
_uid,
|
||||
)
|
||||
return _result, _user_id, _uid
|
||||
|
||||
result, user_id, uid = await get_role_detail_callback(callback_query.data)
|
||||
if user.id != user_id:
|
||||
await callback_query.answer(text="这不是你的按钮!\n" + config.notice.user_mismatch, show_alert=True)
|
||||
return
|
||||
if result == "empty_data":
|
||||
await callback_query.answer(text="此按钮不可用", show_alert=True)
|
||||
return
|
||||
page = 0
|
||||
if result.isdigit():
|
||||
page = int(result)
|
||||
logger.info(
|
||||
"用户 %s[%s] 角色详细信息查询命令请求 || page[%s] uid[%s]",
|
||||
user.full_name,
|
||||
user.id,
|
||||
page,
|
||||
uid,
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
"用户 %s[%s] 角色详细信息查询命令请求 || character_name[%s] uid[%s]",
|
||||
user.full_name,
|
||||
user.id,
|
||||
result,
|
||||
uid,
|
||||
)
|
||||
try:
|
||||
nickname, data = await self.get_characters(uid)
|
||||
except NeedClient:
|
||||
async with self.helper.genshin(user.id, player_id=uid) as client:
|
||||
nickname, data = await self.get_characters(client.player_id, client)
|
||||
if page:
|
||||
buttons = self.gen_button(data, user.id, uid, page)
|
||||
await message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(buttons))
|
||||
await callback_query.answer(f"已切换到第 {page} 页", show_alert=False)
|
||||
return
|
||||
for characters in data.characters:
|
||||
if idToRole(characters.id) == result:
|
||||
break
|
||||
else:
|
||||
await message.delete()
|
||||
await callback_query.answer(
|
||||
f"未在游戏中找到 {result} ,请检查角色是否存在,或者等待角色数据更新后重试",
|
||||
show_alert=True,
|
||||
)
|
||||
return
|
||||
await callback_query.answer(text="正在渲染图片中 请稍等 请不要重复点击按钮", show_alert=False)
|
||||
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
|
||||
render_result = await self.get_render_result(data, nickname, characters.id, uid)
|
||||
render_result.filename = f"role_detail_{uid}_{result}.png"
|
||||
render_result.caption = self.get_caption(data, characters.id)
|
||||
await render_result.edit_media(message, reply_markup=self.get_custom_button(user.id, uid, characters.id))
|
||||
|
||||
@staticmethod
|
||||
def get_custom_button(user_id: int, uid: int, char_id: int) -> Optional[InlineKeyboardMarkup]:
|
||||
return None
|
@ -88,7 +88,7 @@ rich==13.7.1
|
||||
sentry-sdk==2.7.1
|
||||
setuptools==70.2.0
|
||||
shellingham==1.5.4
|
||||
simnet @ git+https://github.com/PaiGramTeam/SIMNet@9839a06bb87403443ac2cbea0ffde4156b05d902
|
||||
simnet @ git+https://github.com/PaiGramTeam/SIMNet@ed7c061d82af4fe8c5a07f0d10c568b5e467662b
|
||||
six==1.16.0
|
||||
smmap==5.0.1
|
||||
sniffio==1.3.1
|
||||
|
BIN
resources/fonts/ZZZ_Default.otf
Normal file
BIN
resources/img/aaa.jpg
Normal file
After Width: | Height: | Size: 196 KiB |
BIN
resources/img/attribute/200.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
resources/img/attribute/201.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
resources/img/attribute/202.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/attribute/203.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/attribute/205.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/attribute/electric.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/attribute/ether.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/attribute/fire.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
resources/img/attribute/ice.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/attribute/physical.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
resources/img/profession/1.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
resources/img/profession/2.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
resources/img/profession/3.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
resources/img/profession/4.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
resources/img/profession/5.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
resources/img/profession/anomaly.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
resources/img/profession/attack.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
resources/img/profession/breakthrough.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
resources/img/profession/defensive.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
resources/img/profession/support.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
resources/img/rarity/A.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
resources/img/rarity/B.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
resources/img/rarity/S.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
297
resources/zzz/agent_detail/agent_detail.html
Normal file
@ -0,0 +1,297 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" gt-area="sea" gt-platform="pc" gt-device="undefined" style="--gpx: 1px;" mi18n-lang="zh-cn">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>绝区零战绩</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="preconnect" href="https://webstatic.hoyoverse.com/">
|
||||
<link rel="stylesheet" href="./css/font.css">
|
||||
<link rel="stylesheet" href="./css/swiper.min.css">
|
||||
<meta name="viewport"
|
||||
content="initial-scale=1,maximum-scale=1,user-scalable=no,width=device-width,viewport-fit=cover">
|
||||
<meta name="description" content="">
|
||||
<meta name="x-op-env" content="v1.0.14">
|
||||
<link href="./css/vendors_f08f35cc.css" rel="stylesheet">
|
||||
<link href="./css/pc_6db636c8.css" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="./css/pc_zzz_bangbooo_all~pc_zzz_challenge_all~pc_zzz_roles_all~pc_zzz_roles_detail_7c5ef2b9.css">
|
||||
<link rel="stylesheet" type="text/css" href="./css/pc_zzz_roles_detail_8479dbdd.css">
|
||||
<link rel="stylesheet" type="text/css" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div data-v-5e800caa="" class="pc-root-layout" id="1081">
|
||||
<div data-v-5e800caa="" class="homeBg_3YryAw-I pc-layout-bg"></div>
|
||||
<div data-v-5e800caa="" class="pc-root-layout__container">
|
||||
<div data-v-5e800caa="" class="shareContainer_2ZR-xeyd">
|
||||
<div class="share-decoIcon tw-absolute tw-right-10 tw-top-10 tw-z-[1] tw-h-[50px] tw-w-[120px]"
|
||||
style="display: none;">
|
||||
</div>
|
||||
<div class="shareBg_1ijiCPI_" style="display: none;"></div>
|
||||
<div class="share-header" style="display: none;"></div>
|
||||
<div class="sharePage_1Rb3Oz8D share-page"> <!---->
|
||||
<div data-v-5e800caa="" class="pc-root-layout__content">
|
||||
<div data-v-7c666a6a="" data-v-5e800caa="" class="role-detail detailPage_1CFihQoV" uid=""
|
||||
switches="[object Object],[object Object],[object Object]">
|
||||
<div class="pc-detail-page-bg detailPageBg_327tx5T6"
|
||||
style="background-image: url('https://act.hoyolab.com/app/mihoyo-zzz-game-record/images/page-bg-pc.9bd180ff.png'); background-color: rgb(1, 1, 1);"></div>
|
||||
<div class="header_1FGsRcEF">
|
||||
<div class="title_rlJZtEfB">代理人详情 - UID {{ uid }}</div>
|
||||
</div>
|
||||
<div data-v-7c666a6a="" class="role-detail-container"
|
||||
style="background: linear-gradient({{ color }} 18%, rgb(1, 1, 1) 42%);">
|
||||
<div data-v-7c666a6a="" class="infos-container">
|
||||
<div data-v-7c666a6a="" class="infos-main-content">
|
||||
<div data-v-7c666a6a="" class="role-infos">
|
||||
<div data-v-7c666a6a="" class="role-name-bg"
|
||||
style="background-color: {{ color }};">
|
||||
</div>
|
||||
<img data-v-7c666a6a="" src="https://act-webstatic.hoyoverse.com/game_record/zzz/role_vertical_painting/role_vertical_painting_{{ char.id }}.png"
|
||||
alt="" class="role-avatar">
|
||||
<div data-v-7c666a6a="" class="role-base-info">
|
||||
<img data-v-7c666a6a="" src="../../img/rarity/{{ char.rarity }}.png"
|
||||
alt="" class="rarity-icon">
|
||||
<div data-v-7c666a6a="" class="base-info">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><p data-v-7c666a6a="">{{ char.name }}</p>
|
||||
<span data-v-7c666a6a="">Lv40</span></div>
|
||||
<div data-v-7c666a6a="">
|
||||
<img data-v-7c666a6a="" src="../../img/attribute/{{ char.element_type }}.png"
|
||||
alt="">
|
||||
<img data-v-7c666a6a="" src="../../img/profession/{{ char.avatar_profession }}.png"
|
||||
alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div data-v-7342b717="" data-v-7c666a6a="" class="rank-list"
|
||||
style="width: 224px; height: 24px;">
|
||||
<svg data-v-7342b717="" viewBox="0 0 80 80"
|
||||
style="width: 24px; height: 24px; color: rgb(62, 62, 62);">
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M30,27.28l-1.72,7.87H34L29.12,57.31h15l7.56-34.62H40.19Q37,26.68,30,27.28Z"></path>
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M40,0A40,40,0,1,0,80,40,40,40,0,0,0,40,0Zm0,71.91A31.91,31.91,0,1,1,71.91,40,32,32,0,0,1,40,71.91Z"></path>
|
||||
</svg>
|
||||
<svg data-v-7342b717="" viewBox="0 0 80 80"
|
||||
style="width: 24px; height: 24px; color: rgb(62, 62, 62);">
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M51.92,22.69H36.82q-9.18,0-10.61,6.49L25,34.72H40l.5-2.07c.36-1.45,1.08-2.17,2.16-2.17a1.33,1.33,0,0,1,1.31.65,4.82,4.82,0,0,1,.09.65,4,4,0,0,1-2,3.76L21.68,50.08l-1.59,7.23H53.57l1.69-7.79H42.57L54.71,41a9.56,9.56,0,0,0,3.8-6.19l1.19-5.63a6.88,6.88,0,0,0,.2-1.94Q59.56,22.7,51.92,22.69Z"></path>
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M40,0A40,40,0,1,0,80,40,40,40,0,0,0,40,0Zm0,71.91A31.91,31.91,0,1,1,71.91,40,32,32,0,0,1,40,71.91Z"></path>
|
||||
</svg>
|
||||
<svg data-v-7342b717="" viewBox="0 0 80 80"
|
||||
style="width: 24px; height: 24px; color: rgb(62, 62, 62);">
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M51.29,22.69h-15q-9.18,0-10.54,6.45l-.87,4.11H39.77l.28-1c.39-1.33,1.09-1.94,2.11-1.82.66.09,1.05.3,1.17.65a1.74,1.74,0,0,1,.23.73,4.27,4.27,0,0,1,0,.83c-.35,1.52-1.43,2.29-3.23,2.29H37.34l-1.69,7.79h3.24c1.26,0,1.93.47,2,1.41a3.71,3.71,0,0,1-.1.91l-.48,2.06C40,48.77,39.18,49.58,38,49.52c-.77,0-1.19-.52-1.27-1.46a4,4,0,0,1,0-.9L37.3,45h-15L21,51a6.51,6.51,0,0,0-.16,2q.33,4.37,7.89,4.37h15q9.18,0,10.72-7.28l.7-3.29a13.56,13.56,0,0,0,.37-3.43,5.45,5.45,0,0,0-.58-1.94q-.82-1.74-4-2.47,6.3-1.73,7.41-6.83L59,29.13a6.28,6.28,0,0,0,.18-1.86Q58.84,22.7,51.29,22.69Z"></path>
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M40,0A40,40,0,1,0,80,40,40,40,0,0,0,40,0Zm0,71.91A31.91,31.91,0,1,1,71.91,40,32,32,0,0,1,40,71.91Z"></path>
|
||||
</svg>
|
||||
<svg data-v-7342b717="" viewBox="0 0 80 80"
|
||||
style="width: 24px; height: 24px; color: rgb(62, 62, 62);">
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M57.26,22.69H34.81L20.14,43.37l-1.56,7.1h17.6l-1.51,6.84h15l1.51-6.84h5l1.75-7.87h-5ZM37.86,42.6H33.29L40,33Z"></path>
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M40,0A40,40,0,1,0,80,40,40,40,0,0,0,40,0Zm0,71.91A31.91,31.91,0,1,1,71.91,40,32,32,0,0,1,40,71.91Z"></path>
|
||||
</svg>
|
||||
<svg data-v-7342b717="" viewBox="0 0 80 80"
|
||||
style="width: 24px; height: 24px; color: rgb(62, 62, 62);">
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M23,42.94H38.11c.59-1.09,1.3-1.64,2.12-1.64a1.53,1.53,0,0,1,1.27.52,13.89,13.89,0,0,1,0,1.9L40.78,47c-.38,1.73-1.16,2.57-2.34,2.51-.92,0-1.34-.55-1.28-1.56.08-.43.15-.84.2-1.23s.11-.76.18-1.11H22.47L21.26,50.9a6.49,6.49,0,0,0-.17,1.91q.35,4.5,8,4.5H44.21Q53.48,57.31,55,50l2-9.3a9.25,9.25,0,0,0,.26-2.64q-.41-5.28-8.32-5.28a25.37,25.37,0,0,0-9.13,1.87l.91-4.16H59.25L61,22.69H27.41Z"></path>
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M40,0A40,40,0,1,0,80,40,40,40,0,0,0,40,0Zm0,71.91A31.91,31.91,0,1,1,71.91,40,32,32,0,0,1,40,71.91Z"></path>
|
||||
</svg>
|
||||
<svg data-v-7342b717="" viewBox="0 0 80 80"
|
||||
style="width: 24px; height: 24px; color: rgb(62, 62, 62);">
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M51.29,22.69h-15q-9.13,0-10.54,6.45L21,51a7.15,7.15,0,0,0-.17,1.9q.35,4.45,7.9,4.46h15q9.21,0,10.76-7.27L56,43a9.1,9.1,0,0,0,.26-2.68q-.41-5.12-8.23-5.11a23.11,23.11,0,0,0-9.1,1.86l.86-3.82a6.46,6.46,0,0,1,.82-2.15,2,2,0,0,1,1.46-.65,1.29,1.29,0,0,1,1.25.64,1.08,1.08,0,0,1,.26.64,2.81,2.81,0,0,1-.12.81l-.09.59H58.11l.91-4a6.28,6.28,0,0,0,.18-1.86Q58.84,22.69,51.29,22.69Zm-11.9,20.6a1.4,1.4,0,0,1,1.27.56.91.91,0,0,1,.15.52,4,4,0,0,1-.13,1.17l-.39,1.77A2.75,2.75,0,0,1,39.47,49a2.12,2.12,0,0,1-1.47.56A1.24,1.24,0,0,1,36.8,49a3,3,0,0,1-.16-.7,4,4,0,0,1,.11-.95l.36-1.69C37.43,44.07,38.19,43.29,39.39,43.29Z"></path>
|
||||
<path data-v-7342b717="" fill="currentColor"
|
||||
d="M40,0A40,40,0,1,0,80,40,40,40,0,0,0,40,0Zm0,71.91A31.91,31.91,0,1,1,71.91,40,32,32,0,0,1,40,71.91Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<img data-v-7c666a6a=""
|
||||
src="{{ char.group_icon_path }}"
|
||||
alt="" class="group-icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<ul data-v-7c666a6a="" class="property-info">
|
||||
{% for prop in props %}
|
||||
<li data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a="">
|
||||
<img data-v-7c666a6a="" src="./images/prop-{{ prop.icon }}-icon.png"
|
||||
alt=""> <span data-v-7c666a6a="">{{ prop.property_name }}</span>
|
||||
</div>
|
||||
<div data-v-7c666a6a="">
|
||||
{% if prop.add != '' %}
|
||||
<span data-v-7c666a6a="" class="base-add-prop">
|
||||
<span data-v-7c666a6a="">{{ prop.base }}</span>
|
||||
<span data-v-7c666a6a="">+{{ prop.add }}</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
<span data-v-7c666a6a="" class="final-prop">{{ prop.final }}</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div data-v-7c666a6a="" class="equipment-info"><h2 data-v-7c666a6a=""><span
|
||||
data-v-7c666a6a="">装备</span> <img data-v-7c666a6a=""
|
||||
src="./images/title-icon.0b3eeb69.png"
|
||||
alt=""></h2>
|
||||
<div data-v-7c666a6a="" class="suit-effects"><h3 data-v-7c666a6a="">
|
||||
套装激活效果</h3>
|
||||
{% set equip_suits = char.equip_suits %}
|
||||
{% if equip_suits %}
|
||||
<ul data-v-7c666a6a="">
|
||||
{% for suit in equip_suits %}
|
||||
<li data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a="">
|
||||
<p data-v-7c666a6a="">{{ suit.name }} [{{ suit.own }}/4]</p>
|
||||
<p data-v-7c666a6a="">
|
||||
{% if suit.own > 3 %}
|
||||
{{ suit.desc2_html | safe }}
|
||||
{% else %}
|
||||
{% if suit.own > 1 %}
|
||||
{{ suit.desc1_html | safe }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</p> <img data-v-7c666a6a=""
|
||||
src="./images/weapon-suit-icon.f75f0d28.png"
|
||||
alt="">
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul data-v-7c666a6a="" class="empty-content">
|
||||
<li data-v-7c666a6a=""><p data-v-7c666a6a="">暂无套装激活效果</p></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div data-v-7c666a6a="" class="main-content">
|
||||
{% set weapon = char.weapon %}
|
||||
{% if weapon %}
|
||||
<div data-v-7c666a6a="" class="weapon-info">
|
||||
<img data-v-7c666a6a="" src="./images/weapon-bg-{{ weapon.rarity }}.png" alt="" class="bg">
|
||||
<img
|
||||
data-v-7c666a6a=""
|
||||
src="{{ weapon.icon }}" alt=""
|
||||
class="icon">
|
||||
{% if weapon.star > 0 %}
|
||||
<img data-v-7c666a6a="" src="./images/role-star-{{ weapon.star }}.png"
|
||||
class="rank">
|
||||
{% endif %}
|
||||
<span data-v-7c666a6a="" class="level">Lv{{ weapon.level }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- 驱动盘-->
|
||||
{% set equips = char.equip_map %}
|
||||
{% for i in range(1, 7) %}
|
||||
<div data-v-7c666a6a="" class="equip-info equip-info-{{ loop.index }}">
|
||||
{% if loop.index < 4 %}
|
||||
{% set side = 'left' %}
|
||||
{% else %}
|
||||
{% set side = 'right' %}
|
||||
{% endif %}
|
||||
{% set equip = equips[loop.index | string] %}
|
||||
{% if equip %}
|
||||
<div data-v-7c666a6a="">
|
||||
<img data-v-7c666a6a="" src="{{ equip.icon }}" alt="" class="icon">
|
||||
<span data-v-7c666a6a="" class="level">Lv{{ equip.level }}</span>
|
||||
</div>
|
||||
<img data-v-7c666a6a=""
|
||||
src="./images/equip-bg-{{ side }}-{{ equip.rarity}}.png" alt=""
|
||||
class="bg">
|
||||
{% else %}
|
||||
<div data-v-7c666a6a="">
|
||||
<img data-v-7c666a6a="" src="./images/equip-disable-bg.png" alt="" class="icon">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% set skills = char.skills %}
|
||||
<div data-v-7c666a6a="" class="skill-info"><h2 data-v-7c666a6a=""><span
|
||||
data-v-7c666a6a="">技能</span> <img data-v-7c666a6a=""
|
||||
src="./images/title-icon.0b3eeb69.png"
|
||||
alt=""></h2>
|
||||
<ul data-v-7c666a6a="">
|
||||
<li data-v-7c666a6a="" class="skill-item">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><img data-v-7c666a6a=""
|
||||
src="./images/skill-icon-0.0d9692b6.png"
|
||||
alt="">
|
||||
<p data-v-7c666a6a=""><span data-v-7c666a6a="">{{ skills[0].level_str }}</span> <span
|
||||
data-v-7c666a6a="">LEVEL</span></p>
|
||||
<h2 data-v-7c666a6a="">普通攻击</h2>
|
||||
<h3 data-v-7c666a6a="">普通攻击</h3></div>
|
||||
</div>
|
||||
</li>
|
||||
<li data-v-7c666a6a="" class="skill-item">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><img data-v-7c666a6a=""
|
||||
src="./images/skill-icon-2.d863591b.png"
|
||||
alt="">
|
||||
<p data-v-7c666a6a=""><span data-v-7c666a6a="">{{ skills[2].level_str }}</span> <span
|
||||
data-v-7c666a6a="">LEVEL</span></p>
|
||||
<h2 data-v-7c666a6a="">闪避</h2>
|
||||
<h3 data-v-7c666a6a="">闪避</h3></div>
|
||||
</div>
|
||||
</li>
|
||||
<li data-v-7c666a6a="" class="skill-item">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><img data-v-7c666a6a=""
|
||||
src="./images/skill-icon-6.3fc55b66.png"
|
||||
alt="">
|
||||
<p data-v-7c666a6a=""><span data-v-7c666a6a="">{{ skills[5].level_str }}</span> <span
|
||||
data-v-7c666a6a="">LEVEL</span></p>
|
||||
<h2 data-v-7c666a6a="">支援技</h2>
|
||||
<h3 data-v-7c666a6a="">支援技</h3></div>
|
||||
</div>
|
||||
</li>
|
||||
<li data-v-7c666a6a="" class="skill-item">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><img data-v-7c666a6a=""
|
||||
src="./images/skill-icon-1.e2f84ffb.png"
|
||||
alt="">
|
||||
<p data-v-7c666a6a=""><span data-v-7c666a6a="">{{ skills[1].level_str }}</span> <span
|
||||
data-v-7c666a6a="">LEVEL</span></p>
|
||||
<h2 data-v-7c666a6a="">特殊技</h2>
|
||||
<h3 data-v-7c666a6a="">特殊技</h3></div>
|
||||
</div>
|
||||
</li>
|
||||
<li data-v-7c666a6a="" class="skill-item">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><img data-v-7c666a6a=""
|
||||
src="./images/skill-icon-3.afdb8abe.png"
|
||||
alt="">
|
||||
<p data-v-7c666a6a=""><span data-v-7c666a6a="">{{ skills[3].level_str }}</span> <span
|
||||
data-v-7c666a6a="">LEVEL</span></p>
|
||||
<h2 data-v-7c666a6a="">连携技</h2>
|
||||
<h3 data-v-7c666a6a="">连携技</h3></div>
|
||||
</div>
|
||||
</li>
|
||||
<li data-v-7c666a6a="" class="skill-item">
|
||||
<div data-v-7c666a6a="">
|
||||
<div data-v-7c666a6a=""><img data-v-7c666a6a=""
|
||||
src="./images/skill-icon-5.3d486da1.png"
|
||||
alt="">
|
||||
<p data-v-7c666a6a=""><span data-v-7c666a6a="">{{ skills[4].level_str }}</span> <span
|
||||
data-v-7c666a6a="">LEVEL</span></p>
|
||||
<h2 data-v-7c666a6a="">核心技</h2>
|
||||
<h3 data-v-7c666a6a="">核心技</h3></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!----> <!----> <!----> <!---->
|
||||
<div data-modal-id="__gt-popup__" data-modal-count="0" data-modal-visible-count="0"
|
||||
class="gt-modal gt-popup-root" style="z-index: 100;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
4
resources/zzz/agent_detail/css/font.css
Normal file
@ -0,0 +1,4 @@
|
||||
@font-face {
|
||||
font-family: 'inpin hongmengti';
|
||||
src: url("../../../fonts/ZZZ_Default.otf")
|
||||
}
|
35
resources/zzz/agent_detail/css/pc_6db636c8.css
Normal file
3859
resources/zzz/agent_detail/css/pc_zzz_roles_detail_8479dbdd.css
Normal file
4609
resources/zzz/agent_detail/css/style.css
Normal file
13
resources/zzz/agent_detail/css/swiper.min.css
vendored
Normal file
37
resources/zzz/agent_detail/css/vendors_f08f35cc.css
Normal file
BIN
resources/zzz/agent_detail/images/detail-logo.cff62426.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/zzz/agent_detail/images/equip-bg-left-A.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
resources/zzz/agent_detail/images/equip-bg-left-B.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
resources/zzz/agent_detail/images/equip-bg-left-S.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
resources/zzz/agent_detail/images/equip-bg-right-A.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
resources/zzz/agent_detail/images/equip-bg-right-B.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
resources/zzz/agent_detail/images/equip-bg-right-S.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
resources/zzz/agent_detail/images/equip-disable-bg.png
Normal file
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 5.6 KiB |
BIN
resources/zzz/agent_detail/images/prop-anomaly-mastery-icon.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.5 KiB |
BIN
resources/zzz/agent_detail/images/prop-atk-icon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
resources/zzz/agent_detail/images/prop-crit-dmg-icon.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
resources/zzz/agent_detail/images/prop-crit-rate-icon.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
resources/zzz/agent_detail/images/prop-def-icon.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
resources/zzz/agent_detail/images/prop-energy-regen-icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
resources/zzz/agent_detail/images/prop-hp-icon.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
resources/zzz/agent_detail/images/prop-impact-icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
resources/zzz/agent_detail/images/prop-pen-ratio-icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
resources/zzz/agent_detail/images/role-star-1.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
resources/zzz/agent_detail/images/role-star-2.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
resources/zzz/agent_detail/images/role-star-3.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
resources/zzz/agent_detail/images/role-star-4.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
resources/zzz/agent_detail/images/role-star-5.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
resources/zzz/agent_detail/images/skill-icon-0.0d9692b6.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
resources/zzz/agent_detail/images/skill-icon-1.e2f84ffb.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
resources/zzz/agent_detail/images/skill-icon-2.d863591b.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
resources/zzz/agent_detail/images/skill-icon-3.afdb8abe.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
resources/zzz/agent_detail/images/skill-icon-5.3d486da1.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/zzz/agent_detail/images/skill-icon-6.3fc55b66.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
resources/zzz/agent_detail/images/title-icon.0b3eeb69.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
resources/zzz/agent_detail/images/weapon-bg-A.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
resources/zzz/agent_detail/images/weapon-bg-B.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
resources/zzz/agent_detail/images/weapon-bg-S.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
resources/zzz/agent_detail/images/weapon-suit-icon.f75f0d28.png
Normal file
After Width: | Height: | Size: 551 B |