mirror of
https://github.com/PaiGramTeam/PamGram.git
synced 2024-11-21 21:58:04 +00:00
✨ Support starrail phone_theme assets
This commit is contained in:
parent
2ab86b71d9
commit
08b558528b
@ -11,6 +11,7 @@ from modules.wiki.base import WikiModel
|
|||||||
from modules.wiki.models.avatar_config import AvatarIcon
|
from modules.wiki.models.avatar_config import AvatarIcon
|
||||||
from modules.wiki.models.head_icon import HeadIcon
|
from modules.wiki.models.head_icon import HeadIcon
|
||||||
from modules.wiki.models.light_cone_config import LightConeIcon
|
from modules.wiki.models.light_cone_config import LightConeIcon
|
||||||
|
from modules.wiki.models.phone_theme import PhoneTheme
|
||||||
from utils.const import PROJECT_ROOT
|
from utils.const import PROJECT_ROOT
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.typedefs import StrOrURL, StrOrInt
|
from utils.typedefs import StrOrURL, StrOrInt
|
||||||
@ -23,6 +24,7 @@ DATA_MAP = {
|
|||||||
"avatar_eidolon": WikiModel.BASE_URL + "avatar_eidolon_icons.json",
|
"avatar_eidolon": WikiModel.BASE_URL + "avatar_eidolon_icons.json",
|
||||||
"avatar_skill": WikiModel.BASE_URL + "skill/info.json",
|
"avatar_skill": WikiModel.BASE_URL + "skill/info.json",
|
||||||
"head_icon": WikiModel.BASE_URL + "head_icons.json",
|
"head_icon": WikiModel.BASE_URL + "head_icons.json",
|
||||||
|
"phone_theme": WikiModel.BASE_URL + "phone_themes.json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -345,6 +347,59 @@ class _HeadIconAssets(_AssetsService):
|
|||||||
raise AssetsCouldNotFound("头像素材图标不存在", target)
|
raise AssetsCouldNotFound("头像素材图标不存在", target)
|
||||||
|
|
||||||
|
|
||||||
|
class _PhoneThemeAssets(_AssetsService):
|
||||||
|
path: Path
|
||||||
|
data: List[PhoneTheme]
|
||||||
|
id_map: Dict[int, PhoneTheme]
|
||||||
|
|
||||||
|
def __init__(self, client: Optional[AsyncClient] = None) -> None:
|
||||||
|
super().__init__(client)
|
||||||
|
self.path = ASSETS_PATH.joinpath("phone_theme")
|
||||||
|
self.path.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
async def initialize(self):
|
||||||
|
logger.info("正在初始化手机壁纸素材图标")
|
||||||
|
html = await self.client.get(DATA_MAP["phone_theme"])
|
||||||
|
self.data = [PhoneTheme(**data) for data in html.json()]
|
||||||
|
self.id_map = {theme.id: theme for theme in self.data}
|
||||||
|
tasks = []
|
||||||
|
for theme in self.data:
|
||||||
|
path = self.path / f"{theme.id}.png"
|
||||||
|
if not path.exists():
|
||||||
|
if theme.urls[0]:
|
||||||
|
tasks.append(self._download(theme.urls[0], path))
|
||||||
|
elif theme.urls[1]:
|
||||||
|
tasks.append(self._download(theme.urls[1], path))
|
||||||
|
if len(tasks) >= 100:
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
tasks = []
|
||||||
|
if tasks:
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
logger.info("手机壁纸素材图标初始化完成")
|
||||||
|
|
||||||
|
def get_path(self, theme: PhoneTheme, ext: str) -> Path:
|
||||||
|
path = self.path / f"{theme.id}.{ext}"
|
||||||
|
return path
|
||||||
|
|
||||||
|
def get_by_id(self, id_: int) -> Optional[PhoneTheme]:
|
||||||
|
return self.id_map.get(id_, None)
|
||||||
|
|
||||||
|
def get_target(self, target: StrOrInt, second_target: StrOrInt = None) -> Optional[PhoneTheme]:
|
||||||
|
data = self.get_by_id(target)
|
||||||
|
if data:
|
||||||
|
return data
|
||||||
|
if second_target:
|
||||||
|
return self.get_target(second_target)
|
||||||
|
raise AssetsCouldNotFound("手机壁纸素材图标不存在", target)
|
||||||
|
|
||||||
|
def icon(self, target: StrOrInt, second_target: StrOrInt = None) -> Path:
|
||||||
|
theme = self.get_target(target, second_target)
|
||||||
|
png_path = self.get_path(theme, "png")
|
||||||
|
if png_path.exists():
|
||||||
|
return png_path
|
||||||
|
raise AssetsCouldNotFound("手机壁纸素材图标不存在", target)
|
||||||
|
|
||||||
|
|
||||||
class AssetsService(BaseService.Dependence):
|
class AssetsService(BaseService.Dependence):
|
||||||
"""asset服务
|
"""asset服务
|
||||||
|
|
||||||
@ -361,6 +416,9 @@ class AssetsService(BaseService.Dependence):
|
|||||||
head_icon: _HeadIconAssets
|
head_icon: _HeadIconAssets
|
||||||
"""头像"""
|
"""头像"""
|
||||||
|
|
||||||
|
phone_theme: _PhoneThemeAssets
|
||||||
|
"""手机壁纸"""
|
||||||
|
|
||||||
light_cone: _LightConeAssets
|
light_cone: _LightConeAssets
|
||||||
"""光锥"""
|
"""光锥"""
|
||||||
|
|
||||||
@ -368,9 +426,11 @@ class AssetsService(BaseService.Dependence):
|
|||||||
self.client = AsyncClient(timeout=60.0)
|
self.client = AsyncClient(timeout=60.0)
|
||||||
self.avatar = _AvatarAssets(self.client)
|
self.avatar = _AvatarAssets(self.client)
|
||||||
self.head_icon = _HeadIconAssets(self.client)
|
self.head_icon = _HeadIconAssets(self.client)
|
||||||
|
self.phone_theme = _PhoneThemeAssets(self.client)
|
||||||
self.light_cone = _LightConeAssets(self.client)
|
self.light_cone = _LightConeAssets(self.client)
|
||||||
|
|
||||||
async def initialize(self): # pylint: disable=W0221
|
async def initialize(self): # pylint: disable=W0221
|
||||||
await self.avatar.initialize()
|
await self.avatar.initialize()
|
||||||
await self.head_icon.initialize()
|
await self.head_icon.initialize()
|
||||||
|
await self.phone_theme.initialize()
|
||||||
await self.light_cone.initialize()
|
await self.light_cone.initialize()
|
||||||
|
@ -119,6 +119,15 @@ class PlayerInfoService(BaseService):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def set_name_card(self, player_id: int, phone_theme_id: int):
|
||||||
|
player_info = await self._players_info_repository.get_by_player_id(player_id)
|
||||||
|
if player_info is None:
|
||||||
|
return False
|
||||||
|
player_info.name_card = phone_theme_id
|
||||||
|
player_info.last_save_time = datetime.now()
|
||||||
|
await self._players_info_repository.update(player_info)
|
||||||
|
return True
|
||||||
|
|
||||||
async def get_form_sql(self, player: Player):
|
async def get_form_sql(self, player: Player):
|
||||||
return await self._players_info_repository.get(player.user_id, player.player_id)
|
return await self._players_info_repository.get(player.user_id, player.player_id)
|
||||||
|
|
||||||
|
23
modules/wiki/models/phone_theme.py
Normal file
23
modules/wiki/models/phone_theme.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class PhoneTheme(BaseModel):
|
||||||
|
id: int
|
||||||
|
"""ID"""
|
||||||
|
name: str
|
||||||
|
"""名称"""
|
||||||
|
description: str
|
||||||
|
"""描述"""
|
||||||
|
story: Optional[str] = None
|
||||||
|
"""故事"""
|
||||||
|
urls: List[str]
|
||||||
|
|
||||||
|
|
||||||
|
# 原始数据
|
||||||
|
|
||||||
|
|
||||||
|
class PhoneThemeConfig(BaseModel):
|
||||||
|
ID: int
|
||||||
|
PhoneThemeMain: str
|
@ -13,6 +13,7 @@ from core.services.template.services import TemplateService
|
|||||||
from core.services.wiki.services import WikiService
|
from core.services.wiki.services import WikiService
|
||||||
from plugins.tools.genshin import GenshinHelper, CharacterDetails
|
from plugins.tools.genshin import GenshinHelper, CharacterDetails
|
||||||
from plugins.tools.head_icon import HeadIconService
|
from plugins.tools.head_icon import HeadIconService
|
||||||
|
from plugins.tools.phone_theme import PhoneThemeService
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.uid import mask_number
|
from utils.uid import mask_number
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ class AvatarListPlugin(Plugin):
|
|||||||
helper: GenshinHelper = None,
|
helper: GenshinHelper = None,
|
||||||
character_details: CharacterDetails = None,
|
character_details: CharacterDetails = None,
|
||||||
head_icon: HeadIconService = None,
|
head_icon: HeadIconService = None,
|
||||||
|
phone_theme: PhoneThemeService = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.cookies_service = cookies_service
|
self.cookies_service = cookies_service
|
||||||
self.assets_service = assets_service
|
self.assets_service = assets_service
|
||||||
@ -72,6 +74,7 @@ class AvatarListPlugin(Plugin):
|
|||||||
self.helper = helper
|
self.helper = helper
|
||||||
self.character_details = character_details
|
self.character_details = character_details
|
||||||
self.head_icon = head_icon
|
self.head_icon = head_icon
|
||||||
|
self.phone_theme = phone_theme
|
||||||
|
|
||||||
async def get_avatar_data(
|
async def get_avatar_data(
|
||||||
self, character_id: int, client: "StarRailClient"
|
self, character_id: int, client: "StarRailClient"
|
||||||
@ -170,6 +173,7 @@ class AvatarListPlugin(Plugin):
|
|||||||
"avatar_datas": avatar_datas, # 角色数据
|
"avatar_datas": avatar_datas, # 角色数据
|
||||||
"has_more": has_more, # 是否显示了全部角色
|
"has_more": has_more, # 是否显示了全部角色
|
||||||
"avatar": (await self.head_icon.get_head_icon(client.player_id)).as_uri(),
|
"avatar": (await self.head_icon.get_head_icon(client.player_id)).as_uri(),
|
||||||
|
"background": (await self.phone_theme.get_phone_theme(client.player_id)).as_uri(),
|
||||||
}
|
}
|
||||||
|
|
||||||
as_document = all_avatars and len(characters) > MAX_AVATAR_COUNT
|
as_document = all_avatars and len(characters) > MAX_AVATAR_COUNT
|
||||||
|
@ -7,10 +7,12 @@ from telegram.ext import CallbackContext, filters
|
|||||||
|
|
||||||
from core.plugin import Plugin, handler
|
from core.plugin import Plugin, handler
|
||||||
from core.services.cookies.error import TooManyRequestPublicCookies
|
from core.services.cookies.error import TooManyRequestPublicCookies
|
||||||
|
from core.services.players.services import PlayerInfoService
|
||||||
from core.services.template.models import RenderResult
|
from core.services.template.models import RenderResult
|
||||||
from core.services.template.services import TemplateService
|
from core.services.template.services import TemplateService
|
||||||
from plugins.tools.genshin import GenshinHelper
|
from plugins.tools.genshin import GenshinHelper
|
||||||
from plugins.tools.head_icon import HeadIconService
|
from plugins.tools.head_icon import HeadIconService
|
||||||
|
from plugins.tools.phone_theme import PhoneThemeService
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.uid import mask_number
|
from utils.uid import mask_number
|
||||||
|
|
||||||
@ -29,10 +31,14 @@ class PlayerStatsPlugins(Plugin):
|
|||||||
template: TemplateService,
|
template: TemplateService,
|
||||||
helper: GenshinHelper,
|
helper: GenshinHelper,
|
||||||
head_icon: HeadIconService,
|
head_icon: HeadIconService,
|
||||||
|
phone_theme: PhoneThemeService,
|
||||||
|
player_info_service: PlayerInfoService,
|
||||||
):
|
):
|
||||||
self.template_service = template
|
self.template_service = template
|
||||||
self.helper = helper
|
self.helper = helper
|
||||||
self.head_icon = head_icon
|
self.head_icon = head_icon
|
||||||
|
self.phone_theme = phone_theme
|
||||||
|
self.player_info_service = player_info_service
|
||||||
|
|
||||||
async def get_uid(self, user_id: int, args: List[str], reply: Optional[Message]) -> int:
|
async def get_uid(self, user_id: int, args: List[str], reply: Optional[Message]) -> int:
|
||||||
"""通过消息获取 uid,优先级:args > reply > self"""
|
"""通过消息获取 uid,优先级:args > reply > self"""
|
||||||
@ -88,7 +94,7 @@ class PlayerStatsPlugins(Plugin):
|
|||||||
except SimnetBadRequest:
|
except SimnetBadRequest:
|
||||||
rogue = None
|
rogue = None
|
||||||
logger.debug(user_info)
|
logger.debug(user_info)
|
||||||
|
await self.set_name_card(uid, user_info.phone_background_image_url)
|
||||||
data = {
|
data = {
|
||||||
"uid": mask_number(uid),
|
"uid": mask_number(uid),
|
||||||
"info": user_info.info,
|
"info": user_info.info,
|
||||||
@ -109,7 +115,7 @@ class PlayerStatsPlugins(Plugin):
|
|||||||
],
|
],
|
||||||
"style": "xianzhou", # nosec
|
"style": "xianzhou", # nosec
|
||||||
"avatar": (await self.head_icon.get_head_icon(uid)).as_uri(),
|
"avatar": (await self.head_icon.get_head_icon(uid)).as_uri(),
|
||||||
"background": user_info.phone_background_image_url,
|
"background": (await self.phone_theme.get_phone_theme(uid)).as_uri(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return await self.template_service.render(
|
return await self.template_service.render(
|
||||||
@ -118,3 +124,13 @@ class PlayerStatsPlugins(Plugin):
|
|||||||
{"width": 650, "height": 440},
|
{"width": 650, "height": 440},
|
||||||
full_page=True,
|
full_page=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def set_name_card(self, player_id: int, image_url: str):
|
||||||
|
if not image_url:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
phone_theme_id = int(image_url.split("/")[-1].replace(".png", ""))
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
return
|
||||||
|
await self.phone_theme.set_to_cache(player_id, phone_theme_id)
|
||||||
|
await self.player_info_service.set_name_card(player_id, phone_theme_id)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Optional, TYPE_CHECKING, List, Union, Tuple
|
from typing import Optional, TYPE_CHECKING, List, Union, Tuple, Dict
|
||||||
|
|
||||||
from simnet.models.starrail.wish import StarRailBannerType
|
from simnet.models.starrail.wish import StarRailBannerType
|
||||||
from telegram import Document, InlineKeyboardButton, InlineKeyboardMarkup, Message, Update, User
|
from telegram import Document, InlineKeyboardButton, InlineKeyboardMarkup, Message, Update, User
|
||||||
@ -29,6 +29,7 @@ from modules.gacha_log.migrate import GachaLogMigrate
|
|||||||
from modules.gacha_log.models import GachaLogInfo
|
from modules.gacha_log.models import GachaLogInfo
|
||||||
from plugins.tools.genshin import PlayerNotFoundError
|
from plugins.tools.genshin import PlayerNotFoundError
|
||||||
from plugins.tools.head_icon import HeadIconService
|
from plugins.tools.head_icon import HeadIconService
|
||||||
|
from plugins.tools.phone_theme import PhoneThemeService
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -57,12 +58,14 @@ class WishLogPlugin(Plugin.Conversation):
|
|||||||
assets: AssetsService,
|
assets: AssetsService,
|
||||||
cookie_service: CookiesService,
|
cookie_service: CookiesService,
|
||||||
head_icon: HeadIconService,
|
head_icon: HeadIconService,
|
||||||
|
phone_theme: PhoneThemeService,
|
||||||
):
|
):
|
||||||
self.template_service = template_service
|
self.template_service = template_service
|
||||||
self.players_service = players_service
|
self.players_service = players_service
|
||||||
self.assets_service = assets
|
self.assets_service = assets
|
||||||
self.cookie_service = cookie_service
|
self.cookie_service = cookie_service
|
||||||
self.head_icon = head_icon
|
self.head_icon = head_icon
|
||||||
|
self.phone_theme = phone_theme
|
||||||
self.gacha_log = GachaLog()
|
self.gacha_log = GachaLog()
|
||||||
self.wish_photo = None
|
self.wish_photo = None
|
||||||
|
|
||||||
@ -292,7 +295,7 @@ class WishLogPlugin(Plugin.Conversation):
|
|||||||
data = await self.gacha_log.get_analysis(user_id, player_id, pool_type, self.assets_service)
|
data = await self.gacha_log.get_analysis(user_id, player_id, pool_type, self.assets_service)
|
||||||
if isinstance(data, str):
|
if isinstance(data, str):
|
||||||
return data
|
return data
|
||||||
data["avatar"] = (await self.head_icon.get_head_icon(player_id)).as_uri()
|
await self.add_theme_data(data, player_id)
|
||||||
png_data = await self.template_service.render(
|
png_data = await self.template_service.render(
|
||||||
"starrail/gacha_log/gacha_log.html",
|
"starrail/gacha_log/gacha_log.html",
|
||||||
data,
|
data,
|
||||||
@ -473,7 +476,7 @@ class WishLogPlugin(Plugin.Conversation):
|
|||||||
await callback_query.answer(png_data, show_alert=True)
|
await callback_query.answer(png_data, show_alert=True)
|
||||||
self.add_delete_message_job(message, delay=1)
|
self.add_delete_message_job(message, delay=1)
|
||||||
else:
|
else:
|
||||||
png_data["avatar"] = (await self.head_icon.get_head_icon(uid)).as_uri()
|
await self.add_theme_data(png_data, uid)
|
||||||
await callback_query.answer(text="正在渲染图片中 请稍等 请不要重复点击按钮", show_alert=False)
|
await callback_query.answer(text="正在渲染图片中 请稍等 请不要重复点击按钮", show_alert=False)
|
||||||
document = False
|
document = False
|
||||||
if png_data["hasMore"] and not group:
|
if png_data["hasMore"] and not group:
|
||||||
@ -494,6 +497,11 @@ class WishLogPlugin(Plugin.Conversation):
|
|||||||
else:
|
else:
|
||||||
await png.edit_media(message)
|
await png.edit_media(message)
|
||||||
|
|
||||||
|
async def add_theme_data(self, data: Dict, player_id: int):
|
||||||
|
data["avatar"] = (await self.head_icon.get_head_icon(player_id)).as_uri()
|
||||||
|
data["background"] = (await self.phone_theme.get_phone_theme(player_id)).as_uri()
|
||||||
|
return data
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def get_migrate_data(
|
async def get_migrate_data(
|
||||||
old_user_id: int, new_user_id: int, old_players: List["Player"]
|
old_user_id: int, new_user_id: int, old_players: List["Player"]
|
||||||
|
64
plugins/tools/phone_theme.py
Normal file
64
plugins/tools/phone_theme.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from core.dependence.assets import AssetsService, AssetsCouldNotFound
|
||||||
|
from core.services.players.services import PlayerInfoService
|
||||||
|
from gram_core.dependence.redisdb import RedisDB
|
||||||
|
from gram_core.plugin import Plugin
|
||||||
|
from utils.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class PhoneThemeService(Plugin):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
player_info_service: PlayerInfoService,
|
||||||
|
asset_service: AssetsService,
|
||||||
|
redis: RedisDB,
|
||||||
|
) -> None:
|
||||||
|
self.player_info_service = player_info_service
|
||||||
|
self.assets = asset_service
|
||||||
|
self.redis = redis.client
|
||||||
|
self.expire = 60 * 60
|
||||||
|
self.qname = "plugins:phone_theme"
|
||||||
|
|
||||||
|
def get_default_phone_theme(self) -> Optional[Path]:
|
||||||
|
try:
|
||||||
|
return self.assets.phone_theme.icon(221000)
|
||||||
|
except AssetsCouldNotFound as e:
|
||||||
|
logger.warning(str(e))
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def get_from_cache(self, player_id: int) -> Optional[int]:
|
||||||
|
key = f"{self.qname}:{player_id}"
|
||||||
|
data = await self.redis.get(key)
|
||||||
|
if data is None:
|
||||||
|
return None
|
||||||
|
return int(data)
|
||||||
|
|
||||||
|
async def set_to_cache(self, player_id: int, phone_theme: int) -> None:
|
||||||
|
key = f"{self.qname}:{player_id}"
|
||||||
|
await self.redis.set(key, phone_theme, ex=self.expire)
|
||||||
|
|
||||||
|
async def get_from_sql(self, player_id: int) -> Optional[int]:
|
||||||
|
player_info = await self.player_info_service.get_by_player_id(player_id)
|
||||||
|
if player_info is None:
|
||||||
|
return None
|
||||||
|
return player_info.name_card
|
||||||
|
|
||||||
|
async def get_phone_theme_id(self, player_id: int) -> Optional[int]:
|
||||||
|
phone_theme = await self.get_from_cache(player_id)
|
||||||
|
if phone_theme is not None:
|
||||||
|
return phone_theme
|
||||||
|
phone_theme = await self.get_from_sql(player_id)
|
||||||
|
if phone_theme is not None:
|
||||||
|
await self.set_to_cache(player_id, phone_theme)
|
||||||
|
return phone_theme
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def get_phone_theme(self, player_id: int):
|
||||||
|
try:
|
||||||
|
phone_theme = await self.get_phone_theme_id(player_id)
|
||||||
|
return self.assets.phone_theme.icon(phone_theme)
|
||||||
|
except AssetsCouldNotFound as e:
|
||||||
|
logger.warning(str(e))
|
||||||
|
return self.get_default_phone_theme()
|
@ -9,7 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container flex flex-col justify-center p-6">
|
<div class="container flex flex-col justify-center p-6">
|
||||||
<div class="header rounded-xl p-2 mb-6">
|
<div class="header rounded-xl p-2 mb-6" style='background-image: url("{{ background }}") '>
|
||||||
<div class="frame rounded-lg border-solid border-2 bg-contain p-4 flex items-center">
|
<div class="frame rounded-lg border-solid border-2 bg-contain p-4 flex items-center">
|
||||||
<img class="w-28 h-28 rounded-full mr-4" src="{{ avatar }}" alt="Avatar">
|
<img class="w-28 h-28 rounded-full mr-4" src="{{ avatar }}" alt="Avatar">
|
||||||
<div>
|
<div>
|
||||||
|
@ -20,11 +20,13 @@
|
|||||||
.header {
|
.header {
|
||||||
background: #e0dad3 url(../gacha_log/img/starrail.png) no-repeat right;
|
background: #e0dad3 url(../gacha_log/img/starrail.png) no-repeat right;
|
||||||
box-shadow: 0 0 8px #72a2ae79;
|
box-shadow: 0 0 8px #72a2ae79;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame {
|
.frame {
|
||||||
border-color: #cdbea8;
|
border-color: #cdbea8;
|
||||||
color: #8a4d30;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-shadow {
|
.text-shadow {
|
||||||
|
@ -20,12 +20,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
background: #e0dad3 url(../gacha_log/img/starrail.png) no-repeat right;
|
/*background: #e0dad3 url(../gacha_log/img/starrail.png) no-repeat right;*/
|
||||||
box-shadow: 0 0 8px #72a2ae79;
|
box-shadow: 0 0 8px #72a2ae79;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame {
|
.frame {
|
||||||
border-color: #cdbea8;
|
border-color: #cdbea8;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<body id="container" class="body_box">
|
<body id="container" class="body_box">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="info_box">
|
<div class="info_box">
|
||||||
<div class="header p-2 rounded-xl bg-contain mb-6">
|
<div class="header p-2 rounded-xl mb-6" style='background-image: url("{{ background }}")'>
|
||||||
<div class="frame p-4 rounded-lg border-solid border-2 flex items-center">
|
<div class="frame p-4 rounded-lg border-solid border-2 flex items-center">
|
||||||
<img class="w-16 h-16 rounded-full mr-4" src="{{ avatar }}" alt="Avatar">
|
<img class="w-16 h-16 rounded-full mr-4" src="{{ avatar }}" alt="Avatar">
|
||||||
<div>
|
<div>
|
||||||
|
@ -6,12 +6,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
background: #e0dad3 url(./img/starrail.png) no-repeat right;
|
/*background: #e0dad3 url(./img/starrail.png) no-repeat right;*/
|
||||||
box-shadow: 0 0 8px #72a2ae79;
|
box-shadow: 0 0 8px #72a2ae79;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame {
|
.frame {
|
||||||
border-color: #cdbea8;
|
border-color: #cdbea8;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@ -225,7 +228,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
color: #fff;
|
color: #fff!important;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 2px 7px;
|
padding: 2px 7px;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<body id="container" class="body_box">
|
<body id="container" class="body_box">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="info_box">
|
<div class="info_box">
|
||||||
<div class="header p-2 rounded-xl bg-contain mb-6">
|
<div class="header p-2 rounded-xl mb-6" style='background-image: url("{{ background }}")'>
|
||||||
<div class="frame p-4 rounded-lg border-solid border-2 flex items-center">
|
<div class="frame p-4 rounded-lg border-solid border-2 flex items-center">
|
||||||
<img class="w-16 h-16 rounded-full mr-4" src="{{ avatar }}" alt="Avatar">
|
<img class="w-16 h-16 rounded-full mr-4" src="{{ avatar }}" alt="Avatar">
|
||||||
<div>
|
<div>
|
||||||
|
Loading…
Reference in New Issue
Block a user