在未绑定CK时,使用本地面板数据展示练度信息

This commit is contained in:
yoimiya-kokomi 2022-09-21 03:15:22 +08:00
parent 1f83a25410
commit bc51c4b1a1
15 changed files with 288 additions and 271 deletions

View File

@ -1,7 +1,11 @@
# 2.0 Alpha.5
* `#面板练度统计` 样式由深色调整为浅色方案
* 重写MysApi相关逻辑可能会导致一些角色信息类的查询异常如遇问题请反馈
* `#面板练度统计` 功能调整
* 在未绑定CK时使用本地面板数据展示练度信息
* 样式由深色调整为浅色方案
* 重写角色数据获取逻辑,可能会导致一些角色信息类的查询异常,如遇问题请反馈
* `#刻晴`、`#老婆`等命令获取角色数据会使用本地面板数据做兜底
* MysApi内部逻辑重写
* 一些已知Bug修复
# 2.0 Alpha.1~4

View File

@ -35,13 +35,6 @@ export async function renderAvatar (e, avatar, renderType = 'card') {
}
}
}
if (!avatar.isProfile) {
let profile = Profile.get(uid, avatar.id, true)
if (profile && profile.hasData) {
// 优先使用Profile数据
avatar = profile
}
}
return await renderCard(e, avatar, renderType)
}
@ -60,11 +53,11 @@ async function renderCard (e, ds, renderType = 'card') {
let data = {}
let custom = char.isCustom
if (!custom) {
let avatar = new Avatar(ds)
let mys = await MysApi.init(e)
let avatar = new Avatar(ds, uid, mys.isSelfCookie)
data = avatar.getData('id,name,sName,level,fetter,cons,weapon,elem,artis,artisSet,imgs,dataSourceName,updateTime')
if (avatar.isProfile || (mys && mys.isSelfCookie)) {
data.talent = await avatar.getTalent(mys)
if (data.talent) {
data.talentMap = ['a', 'e', 'q']
// 计算皇冠个数
data.crownNum = lodash.filter(lodash.map(data.talent, (d) => d.original), (d) => d >= 10).length

View File

@ -1,6 +1,6 @@
import lodash from 'lodash'
import { Common, Profile, Data } from '../../components/index.js'
import { AvatarList, MysApi } from '../../models/index.js'
import { Common, Data } from '../../components/index.js'
import { AvatarList } from '../../models/index.js'
export async function profileStat (e) {
// 缓存时间,单位小时
@ -11,61 +11,41 @@ export async function profileStat (e) {
return false
}
let mys = await MysApi.init(e)
if (!mys || !mys.uid) return true
let uid = mys.uid
let resIndex = await mys.getCharacter()
if (!resIndex) {
let avatars = await AvatarList.getAll(e)
if (!avatars) {
return true
}
if (!await AvatarList.hasTalentCache(uid)) {
e.reply('正在获取角色信息,请稍候...')
}
let avatars = new AvatarList(uid, resIndex.avatars)
let ids = avatars.getIds()
let talentData = await avatars.getTalentData(ids, mys)
let uid = avatars.uid
let talentData = await avatars.getTalentData()
// 天赋等级背景
const talentLvMap = '0,1,1,1,2,2,3,3,3,4,5'.split(',')
let profiles = Profile.getAll(uid)
let avatarRet = []
lodash.forEach(talentData, (avatar) => {
let { talent, id } = avatar
avatar.aeq = talent?.a?.original + talent?.e?.original + talent?.q?.original || 3
avatarRet.push(avatar)
if (profiles[id]) {
let profile = profiles[id]
let profile = avatars.getProfile(id)
if (profile) {
if (profile.hasData) {
let mark = profiles[id].getArtisMark(false)
let mark = profile.getArtisMark(false)
avatar.artisMark = Data.getData(mark, 'mark,markClass,names')
}
}
})
let sortKey = 'level,star,aeq,cons,weapon.level,weapon.star,weapon.affix,fetter'.split(',')
avatarRet = lodash.orderBy(avatarRet, sortKey)
avatarRet = avatarRet.reverse()
let talentNotice = ''
if (!mys.isSelfCookie) {
talentNotice = '未绑定Cookie无法获取天赋列表。请回复 #体力帮助 获取配置教程'
if (!avatars.isSelfCookie) {
talentNotice = '未绑定CK信息可能展示不完全。回复<span>#体力帮助</span>获取CK配置帮助'
}
return await Common.render('character/profile-stat', {
save_id: uid,
uid,
talentLvMap,
talentLvMap: '0,1,1,1,2,2,3,3,3,4,5'.split(','),
avatars: avatarRet,
isSelf: e.isSelf,
talentNotice,
elem: 'hydro'
talentNotice
}, { e, scale: 1.8 })
}

View File

@ -200,7 +200,6 @@ async function abyssPct (e) {
async function abyssTeam (e) {
let mys = await MysApi.init(e, 'cookie')
if (!mys || !mys.uid) {
return true
}
@ -212,27 +211,24 @@ async function abyssTeam (e) {
}
abyssData = abyssData.data
let uid = e.selfUser.uid
let resDetail
let avatars
try {
if (!await AvatarList.hasTalentCache(uid)) {
e.reply('正在获取用户信息,请稍候...')
}
resDetail = await mys.getCharacter()
if (!resDetail || !resDetail.avatars || resDetail.avatars.length <= 3) {
avatars = await AvatarList.getAll(e, mys)
// resDetail = await mys.getCharacter()
if (!avatars) {
e.reply('角色信息获取失败')
return true
}
} catch (err) {
// console.log(err);
}
let avatars = new AvatarList(uid, resDetail.avatars)
let avatarIds = avatars.getIds()
let avatarData = await avatars.getTalentData(avatarIds, mys)
let avatarData = await avatars.getTalentData()
let avatarRet = {}
let data = {}
let noAvatar = {}
lodash.forEach(avatarData, (avatar) => {
let t = avatar.talent
avatarRet[avatar.id] = Math.min(avatar.level, avatar.weapon?.level || 1) * 100 + Math.max(t.a?.original, t.e?.original, t.q?.original) * 1000
@ -254,7 +250,6 @@ async function abyssTeam (e) {
if (teamMark === -1) {
teamMark = 1
}
return {
key: teams.join(','),
mark: teamMark

View File

@ -61,7 +61,7 @@ class App {
let e = this.e
if (event === 'poke') {
if (e.notice_type === 'group') {
if (e.user_id !== Bot.uin || e.msg === '#poke#' || e.isPoke) {
if (e.target_id !== Bot.uin && !e.isPoke) {
return false
}
// group状态下戳一戳的发起人是operator

View File

@ -95,7 +95,10 @@ let Profile = {
if (userData && userData.chars) {
let ret = {}
lodash.forEach(userData.chars, (ds, id) => {
ret[id] = new ProfileData(ds)
let profile = new ProfileData(ds)
if (profile.hasData) {
ret[id] = profile
}
})
return ret
}

View File

@ -4,13 +4,14 @@
* */
import Base from './Base.js'
import lodash from 'lodash'
import { Profile } from '../components/index.js'
import { Artifact, Character, Weapon } from './index.js'
import moment from 'moment'
const charKey = 'name,abbr,sName,star,imgs,weaponType,elem'.split(',')
const charKey = 'name,abbr,sName,star,imgs,face,side,weaponType,elem'.split(',')
export default class Avatar extends Base {
constructor (data = {}) {
constructor (data = {}, pd = false, hasCk = true) {
super()
if (!data.name) {
return false
@ -21,7 +22,29 @@ export default class Avatar extends Base {
}
this.meta = data
this.char = char
this.dataType = data.dataSource ? 'profile' : 'avatar'
let isProfile = data.isProfile
this.dataType = isProfile ? 'profile' : 'avatar'
this.hasCk = hasCk
let profile
let uid
if (isProfile) {
profile = data
} else if (pd) {
if (pd.isProfile) {
profile = pd
} else if (/\d{9}/.test(pd)) {
uid = pd
profile = Profile.get(pd, char.id, true)
}
}
if (profile && profile.isProfile && profile.hasData) {
this.profile = profile
}
this.elem = ((profile && profile.elem) || data.element || data.elem || 'anemo').toLowerCase()
if (char.isTraveler) {
this.char = Character.get({ id: data.id || char.id, elem: this.elem })
uid && char.setTraveler(uid)
}
}
_get (key) {
@ -32,12 +55,17 @@ export default class Avatar extends Base {
}
get dataSourceName () {
if (!this.hasCk && this.profile) {
return this.profile.dataSourceName
}
return this.meta.dataSourceName || '米游社'
}
get updateTime () {
let meta = this.meta
return this.isProfile ? meta.updateTime : moment(new Date()).format('MM-DD HH:mm')
if ((!this.hasCk || this.isProfile) && this.profile) {
return this.profile.updateTime
}
return moment(new Date()).format('MM-DD HH:mm')
}
get isProfile () {
@ -49,13 +77,8 @@ export default class Avatar extends Base {
}
get artis () {
if (this.isProfile && this.meta?.artis) {
return this.meta.artis.toJSON()
}
if (this._artis) {
return this._artis
}
let ret = {}
if (!this.isProfile) {
const posIdx = {
生之花: 1,
死之羽: 2,
@ -71,17 +94,22 @@ export default class Avatar extends Base {
level: ds.level
}
})
this._artis = ret
return this._artis;
return ret
}
if (this.profile && this.profile?.artis) {
return this.profile.artis.toJSON()
}
return false
}
get cons () {
let data = this.meta
return this.isProfile ? data.cons : data.actived_constellation_num
let profile = this.profile
return data.cons || data.actived_constellation_num || profile.cons || 0
}
get weapon () {
let wd = this.meta.weapon
let wd = this.meta?.weapon || this.profile?.weapon
if (!wd || !wd.name) {
return {}
}
@ -97,14 +125,12 @@ export default class Avatar extends Base {
}
}
async getTalent (MysApi) {
if (this.isProfile) {
return this.talent
}
async getTalent (mys) {
if (!this.isProfile && mys && mys.isSelfCookie) {
let char = this.char
let id = char.id
let talent = {}
let talentRes = await MysApi.getDetail(id)
let talentRes = await mys.getDetail(id)
let avatar = this.meta
if (!char || !avatar) {
return {}
@ -131,18 +157,21 @@ export default class Avatar extends Base {
ret.id = id
return ret
}
if (this.profile) {
let profile = this.profile
let talent = profile.talent
talent.id = profile.id
return talent
}
return false
}
get artisSet () {
if (this.isProfile) {
let meta = this.meta
if (meta.artis) {
return meta.artis.getSetData()
}
return {}
}
if (this._artisSet) {
return this._artisSet
}
this._artisSet = false
if (!this.isProfile) {
let artis = this.artis
let setCount = {}
lodash.forEach(artis, (arti, idx) => {
@ -171,6 +200,11 @@ export default class Avatar extends Base {
abbrs: [...abbrs, ...abbrs2],
name: abbrs.length > 1 ? abbrs.join('+') : abbrs2[0]
}
return this._artisSet
}
if (this.profile) {
let profile = this.profile
this._artisSet = profile.artis ? profile.artis.getSetData() : false
}
return this._artisSet || {}
}
}

View File

@ -1,61 +1,56 @@
import Base from './Base.js'
import lodash from 'lodash'
import { Data, Common } from '../components/index.js'
import { Artifact, Character } from './index.js'
import { Data, Common, Profile } from '../components/index.js'
import { Avatar, MysApi } from './index.js'
export default class AvatarList extends Base {
constructor (uid, datas = []) {
constructor (uid, datas = [], withProfile = false) {
super()
if (!uid) {
return false
}
this.uid = uid
let avatars = {}
let abbr = Character.getAbbr()
lodash.forEach(datas, (avatar) => {
let data = Data.getData(avatar, 'id,name,level,star:rarity,cons:actived_constellation_num,fetter')
data.elem = (avatar.element || '').toLowerCase() || 'anemo'
let char = Character.get({ id: data.id, elem: data.elem })
if (char.isTraveler) {
char.setTraveler(uid)
let profiles = {}
if (withProfile) {
profiles = Profile.getAll(uid)
}
data.face = char.face
data.side = char.side
data.abbr = char.abbr
data.weapon = Data.getData(avatar.weapon, 'name,affix:affix_level,level,star:rarity')
data.weapon.abbr = abbr[data?.weapon?.name || ''] || data?.weapon?.name
if (data.star > 5) {
data.star = 5
lodash.forEach(datas, (ds) => {
let avatar = new Avatar(ds, profiles[ds.id] || false)
if (avatar) {
avatars[avatar.id] = avatar
}
let artis = {}
let setCount = {}
lodash.forEach(avatar.reliquaries, (arti) => {
artis[arti.pos] = Data.getData(arti, 'name,level,set:set.name')
setCount[arti.set.name] = (setCount[arti.set.name] || 0) + 1
})
data.artis = artis
data.sets = {}
data.names = []
for (let set in setCount) {
if (setCount[set] >= 2) {
data.sets[set] = setCount[set] >= 4 ? 4 : 2
data.names.push(Artifact.getArtiBySet(set))
// 使用面板数据补全
lodash.forEach(profiles, (profile) => {
if (!avatars[profile.id]) {
let avatar = new Avatar(profile)
if (avatar) {
avatars[avatar.id] = avatar
}
}
avatars[data.id] = data
})
this.avatars = avatars
}
getData (ids) {
getData (ids, keys = '') {
let rets = {}
keys = keys || 'id,name,level,star,cons,fetter,elem,face,side,abbr,weapon,artisSet'
let avatars = this.avatars
lodash.forEach(ids, (id) => {
rets[id] = avatars[id] || {}
rets[id] = avatars[id].getData(keys) || {}
})
return rets
}
getAvatar (id) {
return this.avatars[id]
}
getProfile (id) {
return this.avatars[id]?.profile
}
getIds () {
let rets = []
lodash.forEach(this.avatars, (ds) => {
@ -64,7 +59,11 @@ export default class AvatarList extends Base {
return rets
}
async getTalentData (ids, mys = false) {
async getTalentData (ids = '', mys = false, keys = '') {
if (!ids) {
ids = this.getIds()
}
mys = mys || this._mys
let avatarTalent = await Data.getCacheJSON(`miao:avatar-talent:${this.uid}`)
let needReq = {}
lodash.forEach(ids, (id) => {
@ -72,15 +71,20 @@ export default class AvatarList extends Base {
needReq[id] = true
}
})
let avatars = this.avatars
let needReqIds = lodash.keys(needReq)
if (needReqIds.length > 0 && mys && mys.isSelfCookie) {
if (needReqIds.length > 0) {
if (needReqIds.length > 8) {
this.e && this.e.reply('正在获取角色信息,请稍候...')
}
let num = 10
let ms = 100
let skillRet = []
let avatarArr = lodash.chunk(needReqIds, num)
for (let val of avatarArr) {
for (let id of val) {
skillRet.push(this.getAvatarTalent(id, mys))
let avatar = avatars[id]
skillRet.push(await avatar.getTalent(mys))
}
skillRet = await Promise.all(skillRet)
skillRet = skillRet.filter(item => item.id)
@ -91,7 +95,7 @@ export default class AvatarList extends Base {
})
await Data.setCacheJSON(`miao:avatar-talent:${this.uid}`, avatarTalent, 3600 * 2)
}
let ret = this.getData(ids)
let ret = this.getData(ids, keys)
lodash.forEach(ret, (avatar, id) => {
avatar.talent = avatarTalent[id] || {}
})
@ -99,38 +103,31 @@ export default class AvatarList extends Base {
}
async getAvatarTalent (id, mys) {
let talent = {}
let talentRes = await mys.getDetail(id)
let char = Character.get(id)
let avatar = this.avatars[id]
if (!char || !avatar) {
return talent
return await avatar.getTalent(mys)
}
if (talentRes && talentRes.skill_list) {
talent.id = id
let talentList = lodash.orderBy(talentRes.skill_list, ['id'], ['asc'])
for (let val of talentList) {
let { max_level: maxLv, level_current: lv } = val
if (val.name.includes('普通攻击')) {
talent.a = lv
continue
}
if (maxLv >= 10 && !talent.e) {
talent.e = lv
continue
}
if (maxLv >= 10 && !talent.q) {
talent.q = lv
continue
}
}
}
let ret = char.getAvatarTalent(talent, avatar.cons, 'original')
ret.id = id
return ret
get isSelfCookie () {
return !!this._mys?.isSelfCookie
}
}
AvatarList.hasTalentCache = async function (uid) {
return !!await redis.get(`miao:avatar-talent:${uid}`)
}
AvatarList.getAll = async function (e, mys = false) {
if (!mys) {
mys = await MysApi.init(e)
}
if (!mys || !mys.uid) return false
let uid = mys.uid
let data = await mys.getCharacter()
if (!data) {
return false
}
let ret = new AvatarList(uid, data.avatars, true)
ret.e = e
ret._mys = mys
return ret
}

View File

@ -31,7 +31,8 @@ export default class MysApi {
return false
}
}
return new MysApi(e, uid, mys)
e._mys = new MysApi(e, uid, mys)
return e._mys
}
static async initUser (e, cfg = 'all') {

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 KiB

View File

@ -1,5 +1,10 @@
body {
background: url('./imgs/bg-01.jpg') left center;
background-size: 100% auto;
}
.container {
background-size: cover;
background: url('./imgs/main-01.png') center -25px no-repeat;
background-size: 100% auto;
}
.head-box {
margin-top: 0;
@ -35,7 +40,7 @@
}
#profile-stat .cons {
width: 16px;
text-shadow: 0 0 2px #000;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
}
#profile-stat .fetter {
width: 32px;
@ -72,15 +77,10 @@
.cont .item-name {
padding-left: 5px;
text-align: left;
}
.cont .item-name.star4 {
color: #dfbeff;
}
.cont .item-name.star5 {
color: #ffe4b4;
text-shadow: 0 0 1px #fff, 1px 1px 1px rgba(255, 255, 255, 0.5);
}
.cont .tr.thead {
background: rgba(0, 0, 0, 0.5);
background: rgba(0, 0, 0, 0.4);
font-weight: bold;
}
.cont .tr.thead > div {
@ -94,22 +94,22 @@
color: #333;
}
.cont .tr .td {
box-shadow: 0 0 1px 0 rgba(100, 100, 100, 0.5) inset;
box-shadow: 0 0 1px 0 rgba(100, 100, 100, 0.8) inset;
}
.cont .tr .td.star1 {
background: rgba(171, 171, 171, 0.5);
background: rgba(255, 132, 132, 0.45);
}
.cont .tr .td.star2 {
background: rgba(208, 255, 190, 0.5);
background: rgba(168, 255, 133, 0.45);
}
.cont .tr .td.star3 {
background: rgba(190, 208, 255, 0.5);
background: rgba(137, 168, 255, 0.45);
}
.cont .tr .td.star4 {
background: rgba(223, 190, 255, 0.5);
background: rgba(195, 134, 255, 0.45);
}
.cont .tr .td.star5 {
background: rgba(255, 228, 180, 0.5);
background: rgba(255, 212, 132, 0.45);
}
.cont .tr.thead {
background: rgba(0, 0, 0, 0.5) !important;
@ -118,10 +118,10 @@
color: #d3bc8e !important;
}
.cont .tr:nth-child(odd) {
background: #fff;
background: rgba(255, 255, 255, 0.55);
}
.cont .tr:nth-child(even) {
background: #f0f0f0;
background: rgba(200, 200, 200, 0.55);
}
.cont .tr > div {
text-align: center;
@ -326,7 +326,7 @@
color: #fff;
}
.cont .artis-na {
padding-left: 13px;
padding-left: 12px;
white-space: nowrap;
transform: scale(0.8);
transform-origin: left center;
@ -335,9 +335,14 @@
margin-right: -60px;
}
.cont-notice {
color: #666;
background: rgba(0, 0, 0, 0.7);
text-align: right;
color: #888;
background: rgba(255, 255, 255, 0.4);
font-size: 13px;
text-align: center;
padding: 8px;
}
.cont-notice span {
padding: 0 3px;
color: #555;
}
/*# sourceMappingURL=profile-stat.css.map */

View File

@ -1,4 +1,4 @@
{{extend elemLayout}}
{{extend defaultLayout}}
{{block 'css'}}
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/profile-stat.css"/>
@ -41,8 +41,8 @@
<span class="item-name">{{avatar.abbr||avatar.name}}</span>
</div>
</div>
<div class="td td-lv star{{avatar.star}}">{{avatar.level}}</div>
<div class="td td-cons star{{avatar.star}}">
<div class="td td-lv">{{avatar.level}}</div>
<div class="td td-cons">
<span class="cons avatar cons-{{avatar.cons}}">{{avatar.cons}}</span>
</div>
<div class="td td-fetter">
@ -71,12 +71,11 @@
{{/if}}
</div>
{{set mark = avatar.artisMark || false }}
{{set names = avatar?.artisMark?.names || avatar?.artisSet?.names || []}}
<div class="td td-artis class-{{mark?.markClass||'D'}}">
<div class="item item-banner avatar-artis artis{{avatar?.artisMark?.names?.length||avatar.names.length}}">
{{set names = avatar?.artisMark?.names || avatar?.names || []}}
<div class="item item-banner avatar-artis artis{{names.length}}">
<div class="artis item-icon {{names.length>0?'star5':'no-artis'}}">
{{each avatar?.artisMark?.names || avatar?.names || [] name}}
{{each names name}}
<span class="img"
style="background-image:url({{_res_path}}/meta/reliquaries/icon/{{name}}.png)"></span>
{{/each}}
@ -97,7 +96,7 @@
{{/each}}
</div>
{{if talentNotice}}
<p class="cont-notice">{{talentNotice}}</p>
<p class="cont-notice">{{@talentNotice}}</p>
{{/if}}
</div>
</div>

View File

@ -1,5 +1,11 @@
body {
background: url('./imgs/bg-01.jpg') left center;
background-size: 100% auto;
}
.container {
background-size: cover;
background: url('./imgs/main-01.png') center -25px no-repeat;
background-size: 100% auto;
}
.head-box {
@ -39,7 +45,7 @@
.cons {
width: 16px;
text-shadow: 0 0 2px #000;
text-shadow: 0 0 2px rgba(0, 0, 0, .5);
}
.fetter {
@ -76,18 +82,11 @@
.item-name {
padding-left: 5px;
text-align: left;
&.star4 {
color: #dfbeff;
}
&.star5 {
color: #ffe4b4;
}
text-shadow: 0 0 1px #fff, 1px 1px 1px rgba(255, 255, 255, .5);
}
.tr.thead {
background: rgba(0, 0, 0, .5);
background: rgba(0, 0, 0, .4);
font-weight: bold;
& > div {
@ -105,7 +104,7 @@
color: #333;
.td {
box-shadow: 0 0 1px 0 rgba(100, 100, 100, .5) inset;
box-shadow: 0 0 1px 0 rgba(100, 100, 100, .8) inset;
}
.star(@s, @color) {
@ -113,11 +112,11 @@
background: @color;
}
}
.star(1, rgba(171, 171, 171, .5));
.star(2, rgba(208, 255, 190, .5));
.star(3, rgba(190, 208, 255, .5));
.star(4, rgba(223, 190, 255, .5));
.star(5, rgba(255, 228, 180, .5));
.star(1, rgba(255, 132, 132, 0.45));
.star(2, rgba(168, 255, 133, 0.45));
.star(3, rgba(137, 168, 255, 0.45));
.star(4, rgba(195, 134, 255, 0.45));
.star(5, rgba(255, 212, 132, 0.45));
&.thead {
background: rgba(0, 0, 0, 0.5) !important;
@ -128,11 +127,11 @@
}
&:nth-child(odd) {
background: #fff;
background: rgba(255, 255, 255, .55);
}
&:nth-child(even) {
background: #f0f0f0;
background: rgba(200, 200, 200, .55);
}
& > div {
@ -383,7 +382,7 @@
}
.artis-na {
padding-left: 13px;
padding-left: 12px;
white-space: nowrap;
transform: scale(.8);
transform-origin: left center;
@ -394,8 +393,14 @@
}
.cont-notice {
color: #666;
background: rgba(0, 0, 0, .7);
text-align: right;
color: #888;
background: rgba(255, 255, 255, .4);
font-size: 13px;
text-align: center;
padding: 8px;
span {
padding: 0 3px;
color: #555;
}
}

View File

@ -17,7 +17,8 @@
<div class="avatar-talent">
{{each talentMap k}}
{{set t = talent[k] || {} }}
<span class="talent-item talent-{{k}} talent-{{t.original===10?'crown':'none'}} talent-{{t.level>t.original?'plus':'none'}}">{{t.level}}</span>
<span
class="talent-item talent-{{k}} talent-{{t.original===10?'crown':'none'}} talent-{{t.level>t.original?'plus':'none'}}">{{t.level}}</span>
{{/each}}
</div>
{{else}}
@ -30,9 +31,9 @@
<span class="cons cons-{{weapon.affix}}">{{weapon.affix}}</span>
</div>
</div>
<div class="item avatar-artis artis{{avatar.names.length}}">
<div class="item avatar-artis artis{{avatar.artisSet?.names?.length}}">
<div class="artis item-icon">
{{each avatar.names name}}
{{each avatar.artisSet?.names name}}
<span class="img"
style="background-image:url({{_res_path}}/meta/reliquaries/icon/{{name}}.png)"></span>
{{/each}}