新增*练度统计,请确保Miao-Yunzai为最新版本再更新

This commit is contained in:
Aluxes 2024-04-05 11:28:51 +08:00
parent 9fa319fb98
commit 20f4628084
No known key found for this signature in database
GPG Key ID: 6696152F9C003087
13 changed files with 141 additions and 76 deletions

View File

@ -72,7 +72,7 @@ app.reg({
profileStat: { profileStat: {
name: '面板练度统计', name: '面板练度统计',
fn: ProfileStat.stat, fn: ProfileStat.stat,
rule: /^#(面板|喵喵)练度统计$/, rule: /^#(星铁|原神)?(面板|喵喵)?练度统计$/,
yzRule: /^#*(我的)*(武器|角色|练度|五|四|5|4|星)+(汇总|统计|列表)(force|五|四|5|4|星)*[ |0-9]*$/, yzRule: /^#*(我的)*(武器|角色|练度|五|四|5|4|星)+(汇总|统计|列表)(force|五|四|5|4|星)*[ |0-9]*$/,
yzCheck: () => Cfg.get('profileStat', false) yzCheck: () => Cfg.get('profileStat', false)
}, },
@ -94,7 +94,7 @@ app.reg({
refreshTalent: { refreshTalent: {
name: '强制刷新天赋', name: '强制刷新天赋',
fn: ProfileStat.refreshTalent, fn: ProfileStat.refreshTalent,
rule: /^#(强制)?(刷新|更新)(所有|角色)*(天赋|技能)$/ rule: /^#(星铁|原神)?(强制)?(刷新|更新)(所有|角色)*(天赋|技能)$/
}, },
profileHelp: { profileHelp: {

View File

@ -13,23 +13,32 @@ const ProfileStat = {
}, },
async refreshTalent (e) { async refreshTalent (e) {
let game = /星铁/.test(e.msg) ? 'sr' : 'gs'
e.isSr = game === 'sr'
let mys = await MysApi.init(e) let mys = await MysApi.init(e)
if (!mys || !mys.uid) return false if (!mys || !mys.uid) return false
let player = Player.create(e) let player = Player.create(e, game)
let refreshCount = await player.refreshTalent('', 2) let refreshCount = await player.refreshTalent('', 2)
if (refreshCount) { if (refreshCount && !e.isSr) {
e.reply(`角色天赋更新成功,共${refreshCount}个角色\n你现在可以通过【#练度统计】【#天赋统计】来查看角色信息了...`) e.reply(`角色天赋更新成功,共${refreshCount}个角色\n你现在可以通过【#练度统计】【#天赋统计】来查看角色信息了...`)
} else if (e.isSr) {
e.reply(`角色天赋更新成功,共${refreshCount}个角色\n你现在可以通过【*练度统计】来查看角色信息了...`)
} else { } else {
e.reply('角色天赋未能更新...') e.reply('角色天赋未能更新...')
} }
}, },
// 渲染 // 渲染
// isAvatarList true:角色列表 false练度统计 // mode stat:练度统计 avatar:角色列表 talent:天赋统计
async render (e, mode = 'stat') { async render (e, mode = 'stat') {
let game = /星铁/.test(e.msg) ? 'sr' : 'gs'
e.isSr = game === 'sr'
e.game = game
// 缓存时间,单位小时 // 缓存时间,单位小时
let msg = e.msg.replace('#', '').trim() let msg = e.msg.replace(/#星铁|#/, '').trim()
if (msg === '角色统计' || msg === '武器统计') { if (msg === '角色统计' || msg === '武器统计') {
// 暂时避让一下抽卡分析的关键词 // 暂时避让一下抽卡分析的关键词
return false return false
@ -39,13 +48,12 @@ const ProfileStat = {
mode = 'talent' mode = 'talent'
} }
let mys = await MysApi.init(e) let mys = await MysApi.init(e)
if (!mys || !mys.uid) return false if (!mys || !mys.uid) return false
const uid = mys.uid const uid = mys.uid
let player = Player.create(e) let player = Player.create(e, game)
let avatarRet = await player.refreshAndGetAvatarData({ let avatarRet = await player.refreshAndGetAvatarData({
index: 2, index: 2,
@ -112,7 +120,6 @@ const ProfileStat = {
goldCount: '金卡总数' goldCount: '金卡总数'
} }
let tpl = mode === 'avatar' ? 'character/avatar-list' : 'character/profile-stat' let tpl = mode === 'avatar' ? 'character/avatar-list' : 'character/profile-stat'
return await Common.render(tpl, { return await Common.render(tpl, {
save_id: uid, save_id: uid,
@ -123,7 +130,8 @@ const ProfileStat = {
face, face,
mode, mode,
week, week,
avatars: avatarRet avatars: avatarRet,
game
}, { e, scale: 1.4 }) }, { e, scale: 1.4 })
} }
} }

View File

@ -206,7 +206,7 @@ export default class Avatar extends Base {
level: ds.level || ds.lv || 1, level: ds.level || ds.lv || 1,
promote: lodash.isUndefined(ds.promote) ? Attr.calcPromote(ds.level || ds.lv || 1) : (ds.promote || 0), promote: lodash.isUndefined(ds.promote) ? Attr.calcPromote(ds.level || ds.lv || 1) : (ds.promote || 0),
affix: ds.affix, affix: ds.affix,
...w.getData('star,abbr,type,img') ...w.getData('star,abbr,type,img,imgs')
} }
if (this.weapon.level < 20) { if (this.weapon.level < 20) {
this.weapon.promote = 0 this.weapon.promote = 0

View File

@ -3,7 +3,7 @@ import { Version } from '#miao'
import { Button } from '#miao.models' import { Button } from '#miao.models'
export default class MysApi { export default class MysApi {
constructor (e, uid, mysInfo) { constructor(e, uid, mysInfo) {
this.e = e this.e = e
this.mysInfo = mysInfo this.mysInfo = mysInfo
this.ckInfo = mysInfo.ckInfo this.ckInfo = mysInfo.ckInfo
@ -82,7 +82,7 @@ export default class MysApi {
if (this.mys) { if (this.mys) {
return this.mys return this.mys
} }
this.mys = await e.runtime.getMysApi(targetType, option) this.mys = await e.runtime.getMysApi(targetType, option, e.isSr)
return this.mys return this.mys
} }
@ -146,6 +146,7 @@ export default class MysApi {
} }
async getDetail (id) { async getDetail (id) {
if (this.e.isSr) { return await this.getData('detail', { avatar_id: id, tab_from: 'TabOwned' }) }
return await this.getData('detail', { avatar_id: id }) return await this.getData('detail', { avatar_id: id })
} }

View File

@ -17,7 +17,7 @@ Data.createDir('/data/PlayerData/gs', 'root')
Data.createDir('/data/PlayerData/sr', 'root') Data.createDir('/data/PlayerData/sr', 'root')
export default class Player extends Base { export default class Player extends Base {
constructor (uid, game = 'gs') { constructor(uid, game = 'gs') {
super() super()
uid = uid?._mys?.uid || uid?.uid || uid uid = uid?._mys?.uid || uid?.uid || uid
if (!uid) { if (!uid) {
@ -381,6 +381,9 @@ export default class Player extends Base {
let { talent } = avatar let { talent } = avatar
let ds = avatar.getDetail() let ds = avatar.getDetail()
ds.aeq = talent?.a?.original + talent?.e?.original + talent?.q?.original || 3 ds.aeq = talent?.a?.original + talent?.e?.original + talent?.q?.original || 3
if (avatar.game === 'sr') {
ds.aeq = talent?.a?.original + talent?.e?.original + talent?.q?.original + talent?.t?.original || 4
}
avatarRet[ds.id] = ds avatarRet[ds.id] = ds
let profile = avatar.getProfile() let profile = avatar.getProfile()
@ -407,6 +410,4 @@ export default class Player extends Base {
} }
return avatarRet return avatarRet
} }
} }

View File

@ -1,12 +1,11 @@
import Base from './Base.js' import Base from './Base.js'
import { Data, Format, Meta } from '#miao' import { Data, Format, Meta } from '#miao'
import lodash from 'lodash'
let weaponSet let weaponSet
import lodash from 'lodash'
class Weapon extends Base { class Weapon extends Base {
constructor (meta, game = 'gs') { constructor(meta, game = 'gs') {
if (!meta || !meta.name) { if (!meta || !meta.name) {
return false return false
} }
@ -309,7 +308,6 @@ class Weapon extends Base {
if (!tables[ds.idx]) return true if (!tables[ds.idx]) return true
ds.data[ds.key] = tables[ds.idx] ds.data[ds.key] = tables[ds.idx]
} else if (ds.refine) { } else if (ds.refine) {
lodash.forEach(ds.refine, (r, key) => { lodash.forEach(ds.refine, (r, key) => {
ds.data[key] = ({ refine }) => r[refine] * (ds.buffCount || 1) ds.data[key] = ({ refine }) => r[refine] * (ds.buffCount || 1)
}) })

View File

@ -17,13 +17,6 @@ const MysAvatar = {
return force return force
} }
return force return force
// 暂时不处理ck变更
player._info = 0
player._mys = 0
player.forEachAvatar((avatar) => {
avatar._talent = 0
})
return 2
}, },
/** /**
* 更新米游社角色信息 * 更新米游社角色信息
@ -241,7 +234,8 @@ const MysAvatar = {
let id = char.id let id = char.id
let talent = {} let talent = {}
let talentRes = await mys.getDetail(id) let talentRes = await mys.getDetail(id)
if (talentRes && talentRes.skill_list) { let game = avatar.game
if (game === 'gs' && talentRes && talentRes.skill_list) {
let talentList = lodash.orderBy(talentRes.skill_list, ['id'], ['asc']) let talentList = lodash.orderBy(talentRes.skill_list, ['id'], ['asc'])
for (let val of talentList) { for (let val of talentList) {
let { max_level: maxLv, level_current: lv } = val let { max_level: maxLv, level_current: lv } = val
@ -257,6 +251,27 @@ const MysAvatar = {
talent.q = lv talent.q = lv
} }
} }
} else if (game === 'sr' && talentRes && talentRes.skills) {
let talentList = lodash.orderBy(talentRes.skills, ['point_id'], ['asc'])
for (let val of talentList) {
let { cur_level: lv, anchor } = val
if (anchor.includes('Point01')) {
talent.a = lv
continue
}
if (anchor.includes('Point02')) {
talent.e = lv
continue
}
if (anchor.includes('Point03')) {
talent.q = lv
continue
}
if (anchor.includes('Point04')) {
talent.t = lv
continue
}
}
} }
let ret = char.getAvatarTalent(talent, avatar.cons, 'original') let ret = char.getAvatarTalent(talent, avatar.cons, 'original')
avatar.setTalent(ret, 'original', true) avatar.setTalent(ret, 'original', true)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 KiB

View File

@ -1,11 +1,3 @@
body {
background: url('./imgs/bg-01.jpg') left center;
background-size: 100% auto;
}
.container {
background: url('./imgs/main-01.png') center -25px no-repeat;
background-size: 100% auto;
}
.head-box { .head-box {
margin-top: 0; margin-top: 0;
} }
@ -266,6 +258,10 @@ body {
.cont .tr .lv5.talent-plus { .cont .tr .lv5.talent-plus {
color: #b70000; color: #b70000;
} }
.cont .tr .lv5.crown-sr {
background: url("../common/item/crown-sr-o.png") center center no-repeat rgba(255, 36, 26, 0.55);
background-size: contain;
}
.cont .td-artis { .cont .td-artis {
width: 115px; width: 115px;
text-align: left; text-align: left;
@ -392,4 +388,3 @@ body {
.cont-notice span { .cont-notice span {
margin-left: 5px; margin-left: 5px;
} }
/*# sourceMappingURL=profile-stat.css.map */

View File

@ -1,14 +1,41 @@
{{extend defaultLayout}} {{extend defaultLayout}}
{{set isSr = game === 'sr'}}
{{block 'css'}} {{block 'css'}}
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/profile-stat.css"/> {{if isSr}}
<style>
body {
background: url('{{_res_path}}/character/imgs/bg-02.jpg') left center;
background-size: 100% auto;
}
.container {
background: url('{{_res_path}}/character/imgs/main-02.png') center -25px no-repeat;
background-size: 100% auto;
}
</style>
{{else}}
<style>
body {
background: url('{{_res_path}}/character/imgs/bg-01.jpg') left center;
background-size: 100% auto;
}
.container {
background: url('{{_res_path}}/character/imgs/main-01.png') center -25px no-repeat;
background-size: 100% auto;
}
</style>
{{/if}}
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/profile-stat.css" />
{{/block}} {{/block}}
{{block 'main'}} {{block 'main'}}
<div class="head-box"> <div class="head-box">
<div class="title">#面板练度统计</div> <div class="title">{{isSr?'*':'#'}}面板练度统计</div>
<div class="label">UID:{{uid}} 共{{avatars.length }}名角色</div> <div class="label">UID:{{uid}} 共{{avatars.length}}名角色</div>
</div> </div>
<div id="profile-stat"> <div id="profile-stat">
<div class="cont"> <div class="cont">
@ -17,23 +44,28 @@
<div class="td-idx">#</div> <div class="td-idx">#</div>
<div class="td-name">角色</div> <div class="td-name">角色</div>
<div class="td-lv">Lv</div> <div class="td-lv">Lv</div>
<div class="td-cons">命座</div> <div class="td-cons">{{isSr?'星魂':'命座'}}</div>
{{if !isSr}}
<div class="td-fetter">好感</div> <div class="td-fetter">好感</div>
{{/if}}
<div class="td-talent">A</div> <div class="td-talent">A</div>
<div class="td-talent">E</div> <div class="td-talent">E</div>
<div class="td-talent">Q</div> <div class="td-talent">Q</div>
{{if isSr}}
<div class="td-talent">T</div>
{{/if}}
{{if mode === 'talent'}} {{if mode === 'talent'}}
<div class="td">周本</div> <div class="td">周本</div>
<div class="td">天赋书</div> <div class="td">天赋书</div>
{{else}} {{else}}
<div class="td-weapon">武器</div> <div class="td-weapon">{{isSr?'光锥':'武器'}}</div>
<div class="td-artis">圣遗物</div> <div class="td-artis">{{isSr?'遗器':'圣遗物'}}</div>
{{/if}} {{/if}}
</div> </div>
{{each avatars avatar idx}} {{each avatars avatar idx}}
{{set talent = avatar.talent}} {{set talent = avatar.talent}}
{{set weapon = avatar.weapon}} {{set weapon = avatar.weapon}}
{{set tk = ['a','e','q'] }} {{set tk = isSr?['a','e','q','t']:['a','e','q']}}
<div class="avatar tr"> <div class="avatar tr">
<div class="td td-idx star{{avatar.star}}">{{idx+1}}</div> <div class="td td-idx star{{avatar.star}}">{{idx+1}}</div>
<div class="td td-name star{{avatar.star}}"> <div class="td td-name star{{avatar.star}}">
@ -49,15 +81,26 @@
<div class="td td-cons"> <div class="td td-cons">
<span class="cons avatar cons-{{avatar.cons}}">{{avatar.cons}}</span> <span class="cons avatar cons-{{avatar.cons}}">{{avatar.cons}}</span>
</div> </div>
{{if !isSr}}
<div class="td td-fetter"> <div class="td td-fetter">
<span class="fetter fetter{{['空','荧','旅行者'].includes(avatar.name)?10:avatar.fetter}}"></span> <span class="fetter fetter{{['空','荧','旅行者'].includes(avatar.name)?10:avatar.fetter}}"></span>
</div> </div>
{{/if}}
{{set talentLvMap = [0,1,1,1,2,2,3,3,3,4,5] }} {{set talentLvMap = [0,1,1,1,2,2,3,3,3,4,5] }}
{{set talentALvMap = [0,1,1,2,3,4,5]}}
{{each tk talentKey}} {{each tk talentKey}}
{{set curr = (avatar.talent||{})[talentKey] || {original:1,level:'-'} }} {{set curr = (avatar.talent||{})[talentKey] || {original:1,level:'-'} }}
<div class="td-talent lv{{talentLvMap[curr.original]}} {{curr.level>curr.original?'talent-plus':''}}"> {{if isSr && talentKey === 'a'}}
<div
class="td-talent lv{{talentALvMap[curr.original]}} {{curr.level>curr.original?'talent-plus':''}} {{isSr?'crown-sr':''}}">
{{curr.level}} {{curr.level}}
</div> </div>
{{else}}
<div
class="td-talent lv{{talentLvMap[curr.original]}} {{curr.level>curr.original?'talent-plus':''}} {{isSr?'crown-sr':''}}">
{{curr.level}}
</div>
{{/if}}
{{/each}} {{/each}}
{{if mode === 'talent'}} {{if mode === 'talent'}}
{{set m = avatar.materials || {} }} {{set m = avatar.materials || {} }}
@ -81,7 +124,8 @@
<div class="item-banner star{{weapon.star}}"> <div class="item-banner star{{weapon.star}}">
<span class="level">{{weapon.level}}</span> <span class="level">{{weapon.level}}</span>
<div class="item-icon weapon-icon"> <div class="item-icon weapon-icon">
<span class="img" style="background-image:url({{_res_path}}{{weapon.img}})"></span> <span class="img"
style="background-image:url({{_res_path}}{{isSr?weapon.imgs?.icon2:weapon.img}})"></span>
</div> </div>
<span class="cons weapon cons-{{weapon.affix+1}} star{{weapon.star}}">{{weapon.affix}}</span> <span class="cons weapon cons-{{weapon.affix+1}} star{{weapon.star}}">{{weapon.affix}}</span>
<span class="item-name">{{weapon.abbr}}</span> <span class="item-name">{{weapon.abbr}}</span>
@ -118,16 +162,16 @@
{{if ut.profile || ut.mys}} {{if ut.profile || ut.mys}}
<strong>数据更新时间</strong> <strong>数据更新时间</strong>
{{if ut.profile}} {{if ut.profile}}
<span>#更新面板: {{ut.profile}}</span> <span>{{isSr?'*':'#'}}更新面板: {{ut.profile}}</span>
{{/if}} {{/if}}
{{if ut.mys}} {{if ut.mys}}
<span>米游社: {{ut.mys}}</span> <span>米游社: {{ut.mys}}</span>
<div> <div>
天赋数据每2小时最多更新一次可通过<strong>#刷新天赋</strong>来强制刷新天赋数据需具备有效CK 天赋数据每2小时最多更新一次可通过<strong>{{isSr?'*':'#'}}刷新天赋</strong>来强制刷新天赋数据需具备有效CK
</div> </div>
{{/if}} {{/if}}
{{else}} {{else}}
未绑定CK或CK失效信息可能不完全。发送<strong>#体力帮助</strong>查看CK绑定方法发送<strong>#更新面板</strong>更新游戏内角色展柜信息 未绑定CK或CK失效信息可能不完全。发送<strong>#体力帮助</strong>查看CK绑定方法发送<strong>{{isSr?'*':'#'}}更新面板</strong>更新游戏内角色展柜信息
{{/if}} {{/if}}
</div> </div>

View File

@ -1,13 +1,3 @@
body {
background: url('./imgs/bg-01.jpg') left center;
background-size: 100% auto;
}
.container {
background: url('./imgs/main-01.png') center -25px no-repeat;
background-size: 100% auto;
}
.head-box { .head-box {
margin-top: 0; margin-top: 0;
} }
@ -57,7 +47,8 @@ body {
font-size: 14px; font-size: 14px;
background: none; background: none;
.cons, .level { .cons,
.level {
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
display: inline-block; display: inline-block;
@ -89,7 +80,7 @@ body {
background: rgba(0, 0, 0, .4); background: rgba(0, 0, 0, .4);
font-weight: bold; font-weight: bold;
& > div { &>div {
box-shadow: 0 0 1px 0 rgba(255, 255, 255, .7); box-shadow: 0 0 1px 0 rgba(255, 255, 255, .7);
text-align: center; text-align: center;
} }
@ -107,7 +98,7 @@ body {
box-shadow: 0 0 1px 0 rgba(100, 100, 100, .3) inset; box-shadow: 0 0 1px 0 rgba(100, 100, 100, .3) inset;
} }
.star(@s, @color, @color2:#333) { .star(@s, @color, @color2: #333) {
.td.star@{s} { .td.star@{s} {
background: @color; background: @color;
@ -116,6 +107,7 @@ body {
} }
} }
} }
.star(1, rgba(200, 200, 200, 0.35)); .star(1, rgba(200, 200, 200, 0.35));
.star(2, rgba(168, 255, 133, 0.35)); .star(2, rgba(168, 255, 133, 0.35));
.star(3, rgba(137, 168, 255, 0.35)); .star(3, rgba(137, 168, 255, 0.35));
@ -125,7 +117,7 @@ body {
&.thead { &.thead {
background: rgba(0, 0, 0, 0.5) !important; background: rgba(0, 0, 0, 0.5) !important;
& > div { &>div {
color: #d3bc8e !important; color: #d3bc8e !important;
} }
} }
@ -138,7 +130,7 @@ body {
background: rgba(240, 240, 240, 1); background: rgba(240, 240, 240, 1);
} }
& > div { &>div {
text-align: center; text-align: center;
height: 36px; height: 36px;
vertical-align: middle; vertical-align: middle;
@ -248,9 +240,7 @@ body {
} }
} }
.td-talent { .td-talent {}
}
.talent-plus { .talent-plus {
font-weight: bold; font-weight: bold;
@ -259,7 +249,7 @@ body {
text-shadow: 0px 0px 1px #fff; text-shadow: 0px 0px 1px #fff;
} }
.lv(@lv, @c1, @c2:#333) { .lv(@lv, @c1, @c2: #333) {
.lv@{lv} { .lv@{lv} {
background: @c1; background: @c1;
@ -268,6 +258,7 @@ body {
} }
} }
} }
.lv(1, rgba(60, 63, 65, .3)); .lv(1, rgba(60, 63, 65, .3));
.lv(2, rgba(23, 184, 58, .5), #005800); .lv(2, rgba(23, 184, 58, .5), #005800);
.lv(3, rgba(27, 128, 212, .5)); .lv(3, rgba(27, 128, 212, .5));
@ -280,6 +271,11 @@ body {
&.talent-plus { &.talent-plus {
color: #b70000; color: #b70000;
} }
&.crown-sr {
background: url("../common/item/crown-sr-o.png") center center no-repeat rgba(255, 36, 26, .55);
background-size: contain;
}
} }
@ -298,7 +294,9 @@ body {
text-align: left; text-align: left;
&.class- { &.class- {
&ACE, &MAX {
&ACE,
&MAX {
background: rgba(255, 228, 180, .5); background: rgba(255, 228, 180, .5);
.artis-mark-class { .artis-mark-class {
@ -306,7 +304,8 @@ body {
} }
} }
&SSS, &SS { &SSS,
&SS {
background: rgba(223, 190, 255, .5); background: rgba(223, 190, 255, .5);
.artis-mark-class { .artis-mark-class {
@ -314,7 +313,8 @@ body {
} }
} }
&S, &A { &S,
&A {
background: rgba(190, 208, 255, .5); background: rgba(190, 208, 255, .5);
.artis-mark-class { .artis-mark-class {
@ -322,7 +322,9 @@ body {
} }
} }
&B, &C, &D { &B,
&C,
&D {
background: rgba(171, 171, 171, .5); background: rgba(171, 171, 171, .5);
.artis-mark-class { .artis-mark-class {
@ -410,7 +412,8 @@ body {
text-align: left !important; text-align: left !important;
} }
.td-weekly, .td-material { .td-weekly,
.td-material {
&.today { &.today {
background: rgba(255, 212, 132, 0.35); background: rgba(255, 212, 132, 0.35);

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB