#上传深渊数据使用图片渲染深渊结果

This commit is contained in:
yoimiya-kokomi 2022-08-01 05:42:16 +08:00
parent f93804166a
commit 90617dda2c
17 changed files with 1074 additions and 80 deletions

View File

@ -1,3 +1,8 @@
# 1.9.3
* `#上传深渊数据`使用图片渲染深渊结果
* 功能尚未完全稳定,如遇问题可反馈
# 1.9.2
* `#更新面板`支持配置更新API适配Enka新校验逻辑

View File

@ -24,7 +24,7 @@ export class miao extends plugin {
async dispatch (e) {
let msg = e.original_msg || ''
if (!msg) {
return
return false
}
e.checkAuth = async function (cfg) {
return await checkAuth(e, cfg)
@ -32,7 +32,8 @@ export class miao extends plugin {
e.getMysApi = async function (cfg) {
return await getMysApi(e, cfg)
}
msg = '#' + msg.replace('#', '')
msg = msg.replace('#', '').trim()
msg = '#' + msg
for (let fn in Miao.rule) {
let cfg = Miao.rule[fn]
if (Miao[fn] && new RegExp(cfg.reg).test(msg)) {

View File

@ -7,6 +7,8 @@ import { Cfg } from '../components/index.js'
import lodash from 'lodash'
import fs from 'fs'
import Common from '../components/Common.js'
import Abyss from '../components/models/Abyss.js'
import Avatars from '../components/models/Avatars.js'
export async function consStat (e, { render }) {
if (Cfg.isDisable(e, 'wiki.abyss')) {
@ -392,7 +394,7 @@ export async function abyssTeam (e, { render }) {
}, { e, render, scale: 1.5 })
}
export async function uploadData (e) {
export async function uploadData (e, { render }) {
let MysApi = await e.getMysApi({
auth: 'cookie',
targetType: 'self',
@ -402,9 +404,10 @@ export async function uploadData (e) {
if (!MysApi) return
let ret = {}
let uid = e.selfUser.uid
let resDetail, resAbyss
try {
let resDetail = await MysApi.getCharacter()
let resAbyss = await MysApi.getSpiralAbyss(1)
resDetail = await MysApi.getCharacter()
resAbyss = await MysApi.getSpiralAbyss(1)
// Data.writeJson('/test-data', 'abyss.json', resAbyss);
if (!resDetail || !resAbyss || !resDetail.avatars || resDetail.avatars.length <= 3) {
e.reply('角色信息获取失败')
@ -421,32 +424,59 @@ export async function uploadData (e) {
// console.log(err);
}
if (ret && ret.retcode === 0) {
let msg = [`uid:${uid}本次深渊记录上传成功~ \n多谢支持,φ(>ω<*) 喵~`]
let stat = []
if (ret.data) {
if (resAbyss.floors.length === 0) {
e.reply('暂未获得本期深渊挑战数据...')
return true
}
let abyss = new Abyss(resAbyss)
let avatars = new Avatars(resDetail.avatars)
let avatarIds = abyss.getDisplayAvatars()
let addMsg = function (title, ds) {
let tmp = {}
if (!ds && !ds.avatarId && !ds.percent) {
return
}
let char = Character.get(ds.avatarId)
title = `${title}${char.name}(${(ds.value / 10000).toFixed(1)}W)`
tmp.title = title
tmp.id = char.id
avatarIds.push(char.id)
tmp.value = `${(ds.value / 10000).toFixed(1)}W`
let msg = []
tmp.msg = msg
let pct = (percent, name) => {
if (percent < 0.2) {
title += `,少于${(Math.max(0.1, 100 - percent * 100)).toFixed(1)}%的${name}`
msg.push({
title: '少于',
value: (Math.max(0.1, 100 - percent * 100)).toFixed(1),
name: name
})
} else {
title += `,超过${(Math.min(99.9, percent * 100)).toFixed(1)}%的${name}`
msg.push({
title: '超过',
value: (Math.min(99.9, percent * 100)).toFixed(1),
name: name
})
}
}
pct(ds.percent, char.name)
pct(ds.percentTotal, '总记录')
msg.push(title)
stat.push(tmp)
}
msg.push('当前数据记录:')
addMsg('【最强一击】', ret.data.damage || {})
addMsg('【承受伤害】', ret.data.takeDamage || {})
msg.push('排行会随时间而更新,数据仅供参考~')
addMsg('最强一击', ret.data.damage || {})
addMsg('最高承伤', ret.data.takeDamage || {})
let avatarData = avatars.getData(avatarIds, true)
return await Common.render('stat/abyss-summary', {
abyss: abyss.getData(),
avatars: avatarData,
stat,
save_id: uid
}, { e, render, scale: 1.8 })
} else {
e.reply('暂未获得本期深渊挑战数据...')
return true
}
e.reply(msg.join('\n'))
} else {
e.reply(`${ret.message || '上传失败'},请稍后重试...`)
}

View File

@ -0,0 +1,75 @@
import Base from '../models/Base.js'
import lodash from 'lodash'
import Data from '../Data.js'
import moment from 'moment'
moment.locale('zh-cn')
export default class Abyss extends Base {
constructor (data) {
super()
this.floors = {}
let floors = this.floors
lodash.forEach(data.floors, (floor) => {
let levels = {}
let floorData = {
star: floor.star,
index: floor.index,
levels
}
lodash.forEach(floor.levels, (level) => {
let ds = {
star: level.star
}
levels[level.index] = ds
lodash.forEach(level.battles, (battle) => {
let key = battle.index === 1 ? 'up' : 'down'
let tmp = {}
tmp.timestamp = battle.timestamp
let time = moment(new Date(battle.timestamp * 1000))
tmp.time = time.format('MM-DD HH:mm:ss')
let avatars = []
lodash.forEach(battle.avatars, (avatar) => {
avatars.push(avatar.id)
})
tmp.avatars = avatars
ds[key] = tmp
})
})
floorData.display = levels['3'] || levels['2'] || levels['1']
floors[floor.index] = floorData
})
let keys = 'id:avatar_id,value'
this.reveral = lodash.map(data.reveal_rank, (ds) => Data.getData(ds, keys))
let stat = {}
this.stat = stat
lodash.forEach({
defeat: 'defeat_rank',
dmg: 'damage_rank',
takeDmg: 'take_damage_rank',
e: 'normal_skill_rank',
q: 'energy_skill_rank'
}, (key, dst) => {
stat[dst] = Data.getData(data[key] ? data[key][0] : [], keys)
})
}
getData (floor) {
return Data.getData(this, 'reveral,stat,floors')
}
getDisplayAvatars () {
let ret = {}
lodash.forEach(this.floors, (floor) => {
let display = floor?.display || {}
lodash.forEach(display.up?.avatars || [], (id) => {
ret[id] = true
})
lodash.forEach(display.down?.avatars || [], (id) => {
ret[id] = true
})
})
return lodash.keys(ret)
}
}

View File

@ -172,6 +172,14 @@ let Artifact = {
return false
},
getArtiBySet (name, idx = 1) {
let set = artisMap[name]
if (!set) {
return ''
}
return set.sets[`arti${idx}`].name
},
getMeta () {
return {
attrMap

View File

@ -0,0 +1,48 @@
import Base from './Base.js'
import lodash from 'lodash'
import Data from '../Data.js'
import Artifact from './Artifact.js';
export default class Avatars extends Base {
constructor (datas) {
super()
let avatars = {}
lodash.forEach(datas, (avatar) => {
let data = Data.getData(avatar, 'id,name,level,star:rarity,cons:actived_constellation_num,fetter')
data.weapon = Data.getData(avatar.weapon, 'name,affix:affix_level,level,star:rarity')
let artis = {}
let sets = {}
lodash.forEach(avatar.reliquaries, (arti) => {
artis[arti.pos] = Data.getData(arti, 'name,level,set:set.name')
sets[arti.set.name] = (sets[arti.set.name] || 0) + 1
})
data.artis = artis
data.set = {}
for (let set in sets) {
if (sets[set] >= 4) {
data.set[set] = 4
} else if (sets[set] >= 2) {
data.set[set] = 2
}
}
data.sets = []
lodash.forEach(data.set, (v, k) => {
let name = Artifact.getArtiBySet(k)
if (name) {
data.sets.push(name)
}
})
avatars[data.id] = data
})
this.avatars = avatars
}
getData (ids, withTalent = false) {
let rets = {}
let avatars = this.avatars
lodash.forEach(ids, (id) => {
rets[id] = avatars[id] || {}
})
return rets
}
}

View File

@ -1,20 +1,20 @@
import {attrMark, maxMark, attrMap, usefulAttr} from "../../resources/meta/reliquaries/reliquaries-mark.js";
import lodash from "lodash";
//let meta = Data.readJSON("../../resources/meta/reliquaries", "data.json");
import { attrMark, maxMark, attrMap, usefulAttr } from '../../resources/meta/reliquaries/reliquaries-mark.js'
import lodash from 'lodash'
// let meta = Data.readJSON("../../resources/meta/reliquaries", "data.json");
let meta = {}
let Reliquaries = {
getUseful(char) {
let attrKey = usefulAttr[char] || "";
attrKey = attrKey.split(",");
let attrTitles = [], retMap = {};
getUseful (char) {
let attrKey = usefulAttr[char] || ''
attrKey = attrKey.split(',')
let attrTitles = []; let retMap = {}
lodash.forEach(attrKey, (key) => {
let attr = attrMap[key];
let attr = attrMap[key]
if (attr) {
attrTitles.push(attr.title);
lodash.forEach(attr.attr.split(","), (k) => {
retMap[k] = attrMark[k];
attrTitles.push(attr.title)
lodash.forEach(attr.attr.split(','), (k) => {
retMap[k] = attrMark[k]
})
}
})
@ -24,72 +24,71 @@ let Reliquaries = {
}
},
getMaxMark(char, banTitle = "") {
let markMap = Reliquaries.getUseful(char).mark;
getMaxMark (char, banTitle = '') {
let markMap = Reliquaries.getUseful(char).mark
let markList = [];
let markList = []
lodash.forEach(markMap, (m, title) => {
if (title !== banTitle) {
markList.push(maxMark[title]);
markList.push(maxMark[title])
}
});
})
markList = markList.sort((a, b) => b - a);
let retMaxMark = markList[0];
markList = markList.sort((a, b) => b - a)
let retMaxMark = markList[0]
lodash.forEach(markList, (mark, idx) => {
if (idx > 0 && idx < 4) {
retMaxMark += mark / 6;
retMaxMark += mark / 6
}
});
return retMaxMark;
})
return retMaxMark
},
getMark(char = "", data = []) {
let total = 0;
let markMap = Reliquaries.getUseful(char).mark;
getMark (char = '', data = []) {
let total = 0
let markMap = Reliquaries.getUseful(char).mark
lodash.forEach(data, (ret) => {
ret = ret || [];
let title = ret[0], val = ret[1];
ret = ret || []
let title = ret[0]; let val = ret[1]
if (title && val) {
if (markMap[title]) {
total += markMap[title] * val;
total += markMap[title] * val
}
}
})
return total;
return total
},
getMarkScore(mark, maxMark) {
let pct = mark / maxMark;
getMarkScore (mark, maxMark) {
let pct = mark / maxMark
let scoreMap = [
["D", 0.15],
["C", 0.25],
["B", 0.35],
["A", 0.45],
["S", 0.55],
["SS", 0.65],
["SSS", 0.75],
["ACE", 0.85],
["ACE²", 1]
];
['D', 0.15],
['C', 0.25],
['B', 0.35],
['A', 0.45],
['S', 0.55],
['SS', 0.65],
['SSS', 0.75],
['ACE', 0.85],
['ACE²', 1]
]
for (let idx = 0; idx < scoreMap.length; idx++) {
if (pct < scoreMap[idx][1]) {
return scoreMap[idx][0];
return scoreMap[idx][0]
}
}
},
getSet(name) {
getSet (name) {
for (let idx in meta) {
if (meta[idx].name === name) {
return meta[idx];
return meta[idx]
}
}
}
}
export default Reliquaries;
export default Reliquaries

View File

@ -113,13 +113,12 @@
}
.item-card .item-life {
position: absolute;
top: 0px;
left: 0px;
top: 0;
left: 0;
z-index: 9;
font-size: 13px;
text-align: center;
color: #fff;
border-radius: 2px;
padding: 1px 4px;
border-radius: 3px;
font-family: "tttgbnumber";
@ -139,6 +138,114 @@
.item-card .life5 {
background-color: #ff5722;
}
.item-icon {
width: 100%;
height: 100%;
border-radius: 4px;
position: relative;
overflow: hidden;
}
.item-icon .img {
width: 100%;
height: 100%;
display: block;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.item-icon.star5 {
background-image: url(../common/item/bg5.png);
}
.item-icon.star4 {
background-image: url(../common/item/bg4.png);
}
.avatar-card {
margin: 3px;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8);
}
.avatar-card .card {
border-radius: 7px;
box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3);
position: relative;
overflow: hidden;
background: #e7e5d9;
width: 70px;
}
.avatar-card .avatar-face {
width: 70px;
height: 70px;
border-radius: 7px 7px 20px 0;
background-size: 100%;
background-repeat: no-repeat;
position: relative;
}
.avatar-card .avatar-face .img {
background-position: center bottom;
}
.avatar-card .avatar-face .cons {
border-radius: 0 0 0 5px;
padding: 2px 5px;
}
.avatar-card .avatar-face .avatar-level {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
left: 0;
padding: 2px 5px 2px 3px;
border-radius: 0 4px 0 0;
}
.avatar-card .avatar-talent {
height: 18px;
line-height: 18px;
font-size: 12px;
width: 100%;
color: #222;
text-align: center;
display: none;
}
.avatar-card .cons {
position: absolute;
right: 0;
top: 0;
}
.avatar-detail {
display: flex;
padding: 0 1px 2px;
}
.avatar-detail .item {
width: 31px;
height: 31px;
border-radius: 4px;
margin: 1px;
}
.avatar-weapon .icon {
border-radius: 4px;
}
.avatar-weapon .cons {
top: initial;
bottom: 0;
padding: 1px 3px;
border-radius: 3px 0 0 0;
}
.avatar-artis {
position: relative;
}
.avatar-artis .artis {
background: rgba(0, 0, 0, 0.5);
}
.avatar-artis.artis2 .img {
position: absolute;
width: 24px;
height: 24px;
}
.avatar-artis.artis2 .img:first-child {
left: -2px;
top: -2px;
}
.avatar-artis.artis2 .img:last-child {
right: -2px;
bottom: -2px;
}
.profile {
position: relative;
margin-bottom: 10px;

View File

@ -1,6 +1,7 @@
@import url('tpl/item-card');
@import url('tpl/avatar-card');
@import url('tpl/avatar-profile');
@import url('tpl/artis-detail');

View File

@ -0,0 +1,57 @@
.avatar-card {
margin: 0 0 10px 10px;
border-radius: 7px;
box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3);
height: 88px;
position: relative;
overflow: hidden;
background: #e7e5d9;
}
.avatar-card img {
width: 70px;
height: 70px;
border-radius: 7px 7px 20px 0;
}
.avatar-card.star5 img {
background-image: url(../common/item/bg5.png);
width: 100%;
height: 70px;
/*filter: brightness(1.1);*/
background-size: 100%;
background-repeat: no-repeat;
}
.avatar-card.star4 img {
width: 100%;
height: 70px;
background-image: url(../common/item/bg4.png);
background-size: 100%;
background-repeat: no-repeat;
}
.avatar-card .num {
position: absolute;
top: 0;
right: 0;
z-index: 9;
font-size: 18px;
text-align: center;
color: #fff;
padding: 1px 5px;
border-radius: 4px;
background: rgba(0, 0, 0, 0.5);
}
.avatar-card .name,
.avatar-card .num_name {
position: absolute;
top: 70px;
left: 0;
z-index: 9;
font-size: 12px;
text-align: center;
width: 100%;
height: 16px;
line-height: 18px;
}
.avatar-card .num_name {
font-size: 16px;
}
/*# sourceMappingURL=avatar-card.css.map */

View File

@ -1,15 +1,36 @@
{{set avatar = $data[0]}}
{{set {_res_path,_char} = $data[1]}}
{{set _char = _char || "meta/character/"}}
{{set avatar = $data[0] || {} }}
{{set {_res_path} = $data[1]}}
{{set weapon = avatar.weapon || {} }}
<div class="item">
<div class="item-bg elem-{{avatar.element}}">
<div class="role-box char-{{avatar.name}}">
<img class="role" src="{{_res_path}}{{_char}}/{{avatar.name}}/gacha_card.png"/>
<div class="avatar-card">
<div class="card">
<div class="avatar-face item-icon star{{avatar.star==4?4:5}}">
<span class="img"
style="background-image:url({{_res_path}}/meta/character/{{avatar.name}}/face_2.png)"></span>
<span class="cons cons-{{avatar.cons}}">{{avatar.cons}}</span>
<div class="avatar-level">Lv{{avatar.level}}</div>
</div>
{{ if avatar.cons>0}}
<div class="role-life life{{avatar.cons}}">{{avatar.cons}}命</div>
{{/if}}
<div class="role-name">{{avatar.label || avatar.name}}</div>
<div class="avatar-talent">10-13-13</div>
<div class="avatar-detail">
<div class="item avatar-weapon">
<div class="item-icon star{{weapon.star}}">
<span class="img" style="background-image:url({{_res_path}}/meta/weapons/icon/{{weapon.name}}.png)"></span>
<span class="cons cons-{{weapon.affix}}">{{weapon.affix}}</span>
</div>
</div>
<div class="item avatar-artis artis{{avatar.sets.length}}">
<div class="artis item-icon">
{{each avatar.sets name}}
<span class="img"
style="background-image:url({{_res_path}}/meta/reliquaries/icon/{{name}}.png)"></span>
{{/each}}
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,136 @@
.item-icon {
width: 100%;
height: 100%;
border-radius: 4px;
position: relative;
overflow: hidden;
.img {
width: 100%;
height: 100%;
display: block;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
&.star5 {
background-image: url(../common/item/bg5.png);
}
&.star4 {
background-image: url(../common/item/bg4.png);
}
}
.avatar-card {
margin: 3px;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8);
.card {
border-radius: 7px;
box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%);
position: relative;
overflow: hidden;
background: #e7e5d9;
width: 70px;
}
.avatar-face {
width: 70px;
height: 70px;
border-radius: 7px 7px 20px 0;
background-size: 100%;
background-repeat: no-repeat;
position: relative;
.img {
background-position: center bottom;
}
.cons {
border-radius: 0 0 0 5px;
padding: 2px 5px;
}
.avatar-level {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
left: 0;
padding: 2px 5px 2px 3px;
border-radius: 0 4px 0 0;
}
}
.avatar-talent {
height: 18px;
line-height: 18px;
font-size: 12px;
width: 100%;
color: #222;
text-align: center;
display: none;
}
.cons {
position: absolute;
right: 0;
top: 0;
}
}
.avatar-detail {
display: flex;
padding: 0 1px 2px;
.item {
width: 31px;
height: 31px;
border-radius: 4px;
margin: 1px;
}
}
.avatar-weapon {
.icon {
border-radius: 4px;
}
.cons {
top: initial;
bottom: 0;
padding: 1px 3px;
border-radius: 3px 0 0 0;
}
}
.avatar-artis {
position: relative;
.artis {
background: rgba(0, 0, 0, 0.5)
}
&.artis2 {
.img {
position: absolute;
width: 24px;
height: 24px;
&:first-child {
left: -2px;
top: -2px;
}
&:last-child {
right: -2px;
bottom: -2px;
}
}
}
}

View File

@ -95,13 +95,12 @@
.item-life {
position: absolute;
top: 0px;
left: 0px;
top: 0;
left: 0;
z-index: 9;
font-size: 13px;
text-align: center;
color: #fff;
border-radius: 2px;
padding: 1px 4px;
border-radius: 3px;
font-family: "tttgbnumber";

View File

@ -0,0 +1,184 @@
body,
.container {
width: 690px;
}
.container {
padding: 5px 0 10px 5px;
}
.abyss-stat {
display: flex;
padding: 5px;
}
.abyss-stat .cont {
margin: 5px;
}
.abyss-stat strong {
text-shadow: 0 0 3px #000;
}
.abyss-stat .stat-title {
position: absolute;
top: 0;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
width: 100%;
text-shadow: 0 0 1px #000;
}
.abyss-stat .stat-title span {
display: block;
font-weight: normal;
font-family: NZBZ, sans-serif;
font-size: 24px;
}
.abyss-stat .stat-title strong {
display: block;
font-size: 30px;
}
.abyss-stat .stat-msg {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, 0.65);
padding: 5px 10px;
width: 100%;
text-shadow: 0 0 1px #000;
font-size: 12px;
}
.abyss-stat .stat-msg .msg {
display: block;
}
.abyss-stat .stat-msg .msg strong {
font-size: 15px;
padding: 0 2px;
font-weight: normal;
color: #d3bc8e;
}
.abyss-stat .abyss-notice {
width: 325px;
}
.abyss-stat .abyss-notice .cont-body {
height: 221px;
}
.abyss-stat .abyss-notice ul {
padding-left: 0;
}
.abyss-stat .abyss-notice ul li {
margin-bottom: 13px;
list-style: none;
margin-left: 0;
font-size: 13px;
}
.avatar-banner {
margin-top: -10px;
height: 270px;
width: 158px;
background-repeat: no-repeat;
background-size: 100% auto;
background-position: top center;
}
.cont-title .abyss-star {
font-size: 15px;
color: #fff;
}
.cont-title .abyss-star:before {
content: "";
vertical-align: bottom;
display: inline-block;
width: 20px;
height: 20px;
background: url("./imgs/star.png") center no-repeat;
background-size: contain;
margin-right: 5px;
}
.abyss-floor-team {
display: flex;
}
.abyss-floor-team .line {
width: 1px;
background: rgba(255, 255, 255, 0.5);
height: 80px;
vertical-align: middle;
margin: 15px 10px 0;
}
.abyss-team {
display: flex;
}
.abyss-detail {
display: flex;
width: calc(100% + 40px);
margin: 10px -15px -10px;
}
.abyss-level {
padding: 5px 10px 7px;
width: 33%;
box-shadow: 0 0 1px 0 #fff;
}
.abyss-level:nth-child(even) {
background: rgba(255, 255, 255, 0.1);
}
.abyss-level .info {
margin-bottom: 5px;
display: flex;
}
.abyss-level .title {
white-space: nowrap;
font-weight: bold;
}
.abyss-level .star {
height: 15px;
display: inline-block;
background: url(./imgs/star.png);
background-size: 15px 15px;
margin-left: 5px;
}
.abyss-level .star.star1 {
width: 15px;
margin-right: 30px;
}
.abyss-level .star.star2 {
width: 30px;
margin-right: 15px;
}
.abyss-level .star.star3 {
width: 45px;
margin-right: 0;
}
.abyss-level .time {
text-align: right;
width: 60%;
color: #aaa;
}
.abyss-level .avatars {
display: flex;
width: 100%;
}
.abyss-level .avatars .avatar-list {
display: flex;
position: relative;
}
.abyss-level .avatars .avatar-list.up {
padding-right: 10px;
}
.abyss-level .avatars .avatar-list.up:after {
content: "";
display: block;
position: absolute;
width: 1px;
height: 16px;
background: rgba(255, 255, 255, 0.3);
right: 5px;
top: 50%;
margin-top: -8px;
}
.abyss-level .avatars .avatar-icon {
width: 23px;
height: 23px;
border-radius: 50%;
margin-right: 1px;
}
.abyss-level .avatars .avatar-icon .img {
background-size: auto 100%;
background-position: center;
width: 20px;
height: 20px;
margin: 2px;
}
/*# sourceMappingURL=abyss-summary.css.map */

View File

@ -0,0 +1,98 @@
<script src="../../../../../Yunzai-Botconfig/miao-diy/app/main.js"></script>{{extend defaultLayout}}
{{block 'css'}}
<link rel="stylesheet" type="text/css" href="{{_res_path}}/stat/common.css?v=1.0"/>
<link rel="stylesheet" type="text/css" href="{{_res_path}}/common/tpl.css?v=1.0"/>
<link rel="stylesheet" type="text/css" href="{{_res_path}}/stat/abyss-summary.css?v=1.0"/>
{{/block}}
{{block 'main'}}
{{ set upDown = {up:'上半', down:'下半'} }}
<div class="info_box">
<div class="head-box type">
<div class="title">上传深渊数据</div>
<img class="genshin_logo" src="{{_res_path}}/common/cont/logo.png"/>
</div>
<div class="abyss-stat">
{{each stat ds}}
{{set avatar = avatars[ds.id]}}
<div class="cont">
<div class="stat-title">
<span>{{ds.title}}</span>
<strong>{{ds.value}}</strong>
</div>
<div class="avatar-banner"
style="background-image:url({{_res_path}}/meta/character/{{avatar.name}}/gacha_card.png)"></div>
<div class="stat-msg">
{{each ds.msg msg}}
<div class="msg">{{msg.title}}<strong>{{msg.value}}%</strong>的{{msg.name}}</div>
{{/each}}
</div>
</div>
{{/each}}
<div class="cont abyss-notice">
<div class="cont-title">多谢支持,(>ω<*)喵~</div>
<div class="cont-body">
<ul class="cont-msg">
<li>本次深渊记录上传成功</li>
<li>仅会上传您的角色列表及当期深渊挑战数据,<strong>不会上传其他额外信息</strong></li>
<li>上传的数据将会用于<strong>#深渊使用率</strong><strong>#角色持有率</strong>等统计</li>
<li>统计服务由SG团队<strong>胡桃API</strong>提供</li>
<li>排行为本期排行,会随时间而更新,数据仅供娱乐</li>
</ul>
</div>
</div>
</div>
{{each abyss?.floors floor}}
<div class="cont">
<div class="cont-title">
第{{floor.index}}层
<span class="abyss-star">{{floor.star}}/9</span>
</div>
<div class="cont-body">
<div class="abyss-floor-team">
<div class="abyss-team">
{{each floor.display.up.avatars id}}
<% include(_layout_path+'../tpl/avatar-card.html', [avatars[id],{_res_path}]) %>
{{/each}}
</div>
<div class="line"></div>
<div class="abyss-team">
{{each floor.display.down.avatars id}}
<% include(_layout_path+'../tpl/avatar-card.html', [avatars[id],{_res_path}]) %>
{{/each}}
</div>
</div>
<div class="abyss-detail">
{{each floor.levels level idx}}
<div class="abyss-level">
<div class="info">
<div class="title">
第{{idx}}间
</div>
<span class="star star{{level.star}}"></span>
<div class="time">{{level.up.time}}</div>
</div>
<div class="avatars">
{{each upDown v k}}
<div class="avatar-list {{k}}">
{{each level[k].avatars id}}
{{set avatar = avatars[id]}}
<div class="avatar-icon item-icon star{{avatar.star==4?4:5}}">
<span class="img"
style="background-image:url({{_res_path}}/meta/character/{{avatar.name}}/side.png)"></span>
</div>
{{/each}}
</div>
{{/each}}
</div>
</div>
{{/each}}
</div>
</div>
</div>
{{/each}}
</div>
{{/block}}

View File

@ -0,0 +1,225 @@
body, .container {
width: 690px;
}
.container {
padding: 5px 0 10px 5px;
}
.abyss-stat {
display: flex;
padding: 5px;
.cont {
margin: 5px;
}
strong {
text-shadow: 0 0 3px #000;
}
.stat-title {
position: absolute;
top: 0;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
width: 100%;
text-shadow: 0 0 1px #000;
span {
display: block;
font-weight: normal;
font-family: NZBZ, sans-serif;
font-size: 24px;
}
strong {
display: block;
font-size: 30px;
}
}
.stat-msg {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, 0.65);
padding: 5px 10px;
width: 100%;
text-shadow: 0 0 1px #000;
font-size: 12px;
.msg {
display: block;
strong {
font-size: 15px;
padding: 0 2px;
font-weight: normal;
color: #d3bc8e;
}
}
}
.abyss-notice {
width: 325px;
.cont-body {
height: 221px;
}
ul {
padding-left: 0;
li {
margin-bottom: 13px;
list-style: none;
margin-left: 0;
font-size: 13px;
}
}
}
}
.avatar-banner {
margin-top: -10px;
height: 270px;
width: 158px;
background-repeat: no-repeat;
background-size: 100% auto;
background-position: top center;
}
.cont-title {
.abyss-star {
font-size: 15px;
color: #fff;
&:before {
content: "";
vertical-align: bottom;
display: inline-block;
width: 20px;
height: 20px;
background: url("./imgs/star.png") center no-repeat;
background-size: contain;
margin-right: 5px;
}
}
}
.abyss-floor-team {
display: flex;
.line {
width: 1px;
background: rgba(255, 255, 255, .5);
height: 80px;
vertical-align: middle;
margin: 15px 10px 0;
}
}
.abyss-team {
display: flex;
}
.abyss-detail {
display: flex;
width: calc(100% + 40px);
margin: 10px -15px -10px;
}
.abyss-level {
padding: 5px 10px 7px;
width: 33%;
box-shadow: 0 0 1px 0 #fff;
&:nth-child(even) {
background: rgba(255, 255, 255, .1)
}
.info {
margin-bottom: 5px;
display: flex;
}
.title {
white-space: nowrap;
font-weight: bold;
}
.star {
height: 15px;
display: inline-block;
background: url(./imgs/star.png);
background-size: 15px 15px;
margin-left: 5px;
&.star1 {
width: 15px;
margin-right: 30px;
}
&.star2 {
width: 30px;
margin-right: 15px;
}
&.star3 {
width: 45px;
margin-right: 0;
}
}
.time {
text-align: right;
width: 60%;
color: #aaa;
}
.avatars {
display: flex;
width: 100%;
.avatar-list {
display: flex;
position: relative;
&.up {
padding-right: 10px;
}
&.up:after {
content: "";
display: block;
position: absolute;
width: 1px;
height: 16px;
background: rgba(255, 255, 255, .3);
right: 5px;
top: 50%;
margin-top: -8px;
}
}
.avatar-icon {
width: 23px;
height: 23px;
border-radius: 50%;
margin-right: 1px;
.img {
background-size: auto 100%;
background-position: center;
width: 20px;
height: 20px;
margin: 2px;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB