feat: GPU power display, font enlargement, countdown timer, dim color fix, miner_uid login
This commit is contained in:
+9
-1
@@ -1109,6 +1109,14 @@ func tryNvidiaSMI() []GPUInfo {
|
||||
} else {
|
||||
fan = parseFloat(fanStr)
|
||||
}
|
||||
powerStr := strings.TrimSpace(parts[9])
|
||||
powerStr = strings.Trim(powerStr, "[]")
|
||||
var power float64
|
||||
if powerStr == "N/A" || powerStr == "" {
|
||||
power = 0
|
||||
} else {
|
||||
power = parseFloat(powerStr)
|
||||
}
|
||||
gpus = append(gpus, GPUInfo{
|
||||
Name: parts[1],
|
||||
VRAMTotalMB: parseFloat(parts[2]),
|
||||
@@ -1117,7 +1125,7 @@ func tryNvidiaSMI() []GPUInfo {
|
||||
LoadPercent: parseFloat(parts[6]),
|
||||
CoreClock: parseFloat(parts[7]),
|
||||
MemClock: parseFloat(parts[8]),
|
||||
Power: parseFloat(parts[9]),
|
||||
Power: power,
|
||||
FanSpeed: fan,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
:root {
|
||||
--bg: #0a0d13; --card: #111520; --sec: #161b28; --border: #1e253a;
|
||||
--accent: #00e5a0; --warn: #ffb020; --danger: #ff4060;
|
||||
--text: #e2e6ef; --dim: #5a627a; --dim-bar: #1e2336;
|
||||
--text: #e2e6ef; --dim: #7a829a; --dim-bar: #1e2336;
|
||||
--mono: 'JetBrains Mono','Menlo',monospace;
|
||||
}
|
||||
* { margin:0; padding:0; box-sizing:border-box }
|
||||
@@ -65,35 +65,35 @@
|
||||
.device-card { background:var(--card); border:1px solid var(--border); border-radius:10px; transition:opacity .3s,border-color .2s,box-shadow .2s }
|
||||
.device-card:hover { border-color:#28304a; box-shadow:0 4px 24px rgba(0,0,0,.2) }
|
||||
.device-card.offline { opacity:.55 } .device-card.offline:hover { opacity:.75 }
|
||||
.dc-hd { display:flex; align-items:center; justify-content:space-between; padding:8px 14px 0; gap:6px }
|
||||
.dc-name { font-size:12px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
|
||||
.dc-time { font-size:9px; color:var(--dim); font-family:var(--mono); flex-shrink:0 }
|
||||
.dc-sub { padding:1px 14px 0; font-size:9px; color:var(--dim) }
|
||||
.dc-hd { display:flex; align-items:center; justify-content:space-between; padding:10px 16px 0; gap:6px }
|
||||
.dc-name { font-size:13px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
|
||||
.dc-time { font-size:10px; color:var(--dim); font-family:var(--mono); flex-shrink:0; display:flex; align-items:center; gap:4px }
|
||||
.dc-sub { padding:1px 16px 0; font-size:10px; color:var(--dim) }
|
||||
.dc-bd { padding:5px 0 0 }
|
||||
.dc-col { padding:0 12px 8px; flex:1 1 0; min-width:0; display:flex; flex-direction:column }
|
||||
.dc-left { border-right:1px solid var(--border) }
|
||||
|
||||
.sec { background:var(--sec); border-radius:6px; padding:6px 10px }
|
||||
.sec-tt { font-size:8px; font-weight:600; letter-spacing:.8px; text-transform:uppercase; color:var(--dim); margin-bottom:3px }
|
||||
.sec { background:var(--sec); border-radius:6px; padding:8px 12px }
|
||||
.sec-tt { font-size:10px; font-weight:600; letter-spacing:.8px; text-transform:uppercase; color:var(--dim); margin-bottom:4px }
|
||||
.sec-tt .hl { color:var(--text) }
|
||||
.hw-row { display:flex; align-items:center; gap:6px }
|
||||
.hw-row .sec-tt { margin-bottom:0 }
|
||||
.tag-on { background:rgba(0,229,160,.12); color:var(--accent); border:none; font-size:7px; padding:0 5px; line-height:16px; border-radius:8px }
|
||||
.tag-off { background:rgba(255,64,96,.1); color:var(--danger); border:none; font-size:7px; padding:0 5px; line-height:16px; border-radius:8px }
|
||||
.info-row { display:flex; justify-content:space-between; align-items:center; font-size:9px; line-height:1.8 }
|
||||
.tag-on { background:rgba(0,229,160,.12); color:var(--accent); border:none; font-size:8px; padding:0 6px; line-height:18px; border-radius:8px }
|
||||
.tag-off { background:rgba(255,64,96,.1); color:var(--danger); border:none; font-size:8px; padding:0 6px; line-height:18px; border-radius:8px }
|
||||
.info-row { display:flex; justify-content:space-between; align-items:center; font-size:10px; line-height:1.8 }
|
||||
.info-row .label { color:var(--dim) } .info-row .value { font-family:var(--mono); font-weight:500 }
|
||||
|
||||
.gpu-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:4px }
|
||||
.gpu-block { background:rgba(0,0,0,.2); border-radius:5px; padding:5px; cursor:pointer; transition:background .2s,transform .15s }
|
||||
.gpu-block { background:rgba(0,0,0,.2); border-radius:5px; padding:6px; cursor:pointer; transition:background .2s,transform .15s }
|
||||
.gpu-block:hover { background:rgba(0,229,160,.06); transform:translateY(-1px) }
|
||||
.gpu-active { background:rgba(0,229,160,.12); border:1px solid var(--accent); transform:translateY(-1px) }
|
||||
.gb-top { display:flex; justify-content:space-between; align-items:center; margin-bottom:3px; gap:3px }
|
||||
.gb-temp { font-size:10px; font-weight:700; font-family:var(--mono) }
|
||||
.gb-fan { font-size:9px; color:var(--dim); font-family:var(--mono); display:flex; align-items:center; gap:2px }
|
||||
.gb-bar { position:relative; height:12px; background:var(--dim-bar); border-radius:3px; overflow:hidden; margin-bottom:2px }
|
||||
.gb-temp { font-size:11px; font-weight:700; font-family:var(--mono) }
|
||||
.gb-fan { font-size:10px; color:var(--dim); font-family:var(--mono); display:flex; align-items:center; gap:2px }
|
||||
.gb-bar { position:relative; height:14px; background:var(--dim-bar); border-radius:3px; overflow:hidden; margin-bottom:2px }
|
||||
.gb-fill { height:100%; border-radius:3px; transition:width .5s ease }
|
||||
.gb-pct { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:7px; font-weight:700; font-family:var(--mono); color:#fff; text-shadow:0 1px 2px rgba(0,0,0,.6) }
|
||||
.gb-info { display:flex; justify-content:space-between; font-size:8px; font-family:var(--mono); margin-top:2px }
|
||||
.gb-pct { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:8px; font-weight:700; font-family:var(--mono); color:#fff; text-shadow:0 1px 2px rgba(0,0,0,.6) }
|
||||
.gb-info { display:flex; justify-content:space-between; font-size:9px; font-family:var(--mono); margin-top:2px }
|
||||
|
||||
.gpu-popover .ant-popover { width:100%!important; left:0!important }
|
||||
.gpu-popover .ant-popover-inner { width:100%!important }
|
||||
@@ -115,20 +115,20 @@
|
||||
.gpu-pop-row .info-row .label { color:var(--dim); white-space:nowrap }
|
||||
.gpu-pop-row .info-row .value { color:var(--text); font-family:var(--mono); font-weight:500; white-space:nowrap }
|
||||
|
||||
.m-hr-row { display:flex; align-items:center; gap:5px; margin-bottom:3px }
|
||||
.m-hr-row { display:flex; align-items:center; gap:5px; margin-bottom:4px }
|
||||
.m-hr-row:last-child { margin-bottom:0 }
|
||||
.m-hr-lbl { width:20px; text-align:right; font-family:var(--mono); font-size:8px; color:var(--dim); flex-shrink:0 }
|
||||
.m-hr-bar { flex:1; height:5px; background:var(--dim-bar); border-radius:3px; overflow:hidden }
|
||||
.m-hr-lbl { width:22px; text-align:right; font-family:var(--mono); font-size:9px; color:var(--dim); flex-shrink:0 }
|
||||
.m-hr-bar { flex:1; height:6px; background:var(--dim-bar); border-radius:3px; overflow:hidden }
|
||||
.m-hr-fill { height:100%; border-radius:3px; transition:width .4s ease }
|
||||
.m-hr-val { min-width:65px; text-align:right; font-family:var(--mono); font-size:8px; font-weight:500; flex-shrink:0 }
|
||||
.m-status { display:flex; align-items:center; gap:5px; font-size:9px; margin-bottom:4px }
|
||||
.m-agent,.m-country { color:var(--dim); font-size:8px; font-family:var(--mono); margin-left:auto }
|
||||
.m-shares { display:flex; justify-content:space-between; margin-top:4px; font-family:var(--mono); font-size:8px }
|
||||
.m-hr-val { min-width:70px; text-align:right; font-family:var(--mono); font-size:9px; font-weight:500; flex-shrink:0 }
|
||||
.m-status { display:flex; align-items:center; gap:5px; font-size:10px; margin-bottom:5px }
|
||||
.m-agent,.m-country { color:var(--dim); font-size:9px; font-family:var(--mono); margin-left:auto }
|
||||
.m-shares { display:flex; justify-content:space-between; margin-top:5px; font-family:var(--mono); font-size:9px }
|
||||
.m-sh.valid { color:var(--accent) } .m-sh.stale { color:var(--warn) } .m-sh.invalid { color:var(--danger) }
|
||||
.m-times { display:flex; gap:10px; margin-top:4px; font-size:8px }
|
||||
.m-times { display:flex; gap:10px; margin-top:5px; font-size:9px }
|
||||
.m-times span { color:var(--dim) } .m-times .v { font-family:var(--mono) }
|
||||
.chart-box { background:rgba(0,0,0,.15); border-radius:4px; padding:5px 6px; margin-top:5px; overflow:hidden }
|
||||
.chart-lbl { font-size:7px; color:var(--dim); font-family:var(--mono); margin-bottom:3px }
|
||||
.chart-box { background:rgba(0,0,0,.15); border-radius:4px; padding:6px 8px; margin-top:6px; overflow:hidden }
|
||||
.chart-lbl { font-size:8px; color:var(--dim); font-family:var(--mono); margin-bottom:3px }
|
||||
.chart-empty { color:var(--dim); font-size:8px; text-align:center; padding:10px 0 }
|
||||
|
||||
.off-actions { display:flex; justify-content:flex-end; padding-top:0 }
|
||||
@@ -222,7 +222,7 @@
|
||||
<!-- 全部在线 -->
|
||||
<template v-for="name in onlineDevices">
|
||||
<div class="device-card" :key="name">
|
||||
<div class="dc-hd"><span class="dc-name">{{ name }}</span><span class="dc-time">{{ ago(devices[name].info.last_seen) }}</span></div>
|
||||
<div class="dc-hd"><span class="dc-name">{{ name }}</span><span class="dc-time">{{ countdown(devices[name].info.last_seen) }}<a-icon v-if="refreshing" type="loading" style="font-size:10px;color:var(--accent)" /></span></div>
|
||||
<div class="dc-sub" v-if="devices[name].info.motherboard && (devices[name].info.motherboard.manufacturer || devices[name].info.motherboard.product)">{{ devices[name].info.motherboard.manufacturer }} {{ devices[name].info.motherboard.product }}</div>
|
||||
<a-row :gutter="[12,0]" type="flex" class="dc-bd">
|
||||
<a-col :xs="24" :sm="24" :md="12" class="dc-col dc-left" style="flex:1 1 0">
|
||||
@@ -243,7 +243,7 @@
|
||||
<template v-for="name in hwOnlyDevices">
|
||||
<div class="sec-div" :key="'sep-hw-'+name" v-if="name===hwOnlyDevices[0] && onlineDevices.length>0">{{ hwOnlyDevices.length }} 台仅硬件在线</div>
|
||||
<div class="device-card" :key="name">
|
||||
<div class="dc-hd"><span class="dc-name">{{ name }}</span><span class="dc-time">{{ ago(devices[name].info.last_seen) }}</span></div>
|
||||
<div class="dc-hd"><span class="dc-name">{{ name }}</span><span class="dc-time">{{ countdown(devices[name].info.last_seen) }}<a-icon v-if="refreshing" type="loading" style="font-size:10px;color:var(--accent)" /></span></div>
|
||||
<div class="dc-sub" v-if="devices[name].info.motherboard && (devices[name].info.motherboard.manufacturer || devices[name].info.motherboard.product)">{{ devices[name].info.motherboard.manufacturer }} {{ devices[name].info.motherboard.product }}</div>
|
||||
<div class="dc-bd" style="padding:4px 14px 8px">
|
||||
<cpu-section :cpu="getLive(name).cpu||{}" :info="devices[name].info" :is-on="true"></cpu-section>
|
||||
@@ -257,7 +257,7 @@
|
||||
<template v-for="name in poolOnlyDevices">
|
||||
<div class="sec-div" :key="'sep-pool-'+name" v-if="name===poolOnlyDevices[0]">{{ poolOnlyDevices.length }} 台仅矿池在线</div>
|
||||
<div class="device-card offline" :key="name">
|
||||
<div class="dc-hd"><span class="dc-name">{{ name }}</span><span class="dc-time">{{ ago(devices[name].info.last_seen) }}</span></div>
|
||||
<div class="dc-hd"><span class="dc-name">{{ name }}</span><span class="dc-time">{{ countdown(devices[name].info.last_seen) }}<a-icon v-if="refreshing" type="loading" style="font-size:10px;color:var(--accent)" /></span></div>
|
||||
<div class="dc-bd" style="padding:4px 14px 8px">
|
||||
<mining-section :mining="devices[name].mining" :history="devices[name].hash_history"></mining-section>
|
||||
</div>
|
||||
@@ -270,7 +270,7 @@
|
||||
<div class="device-card offline" :key="name">
|
||||
<div class="dc-hd">
|
||||
<span class="dc-name">{{ name }}</span>
|
||||
<span class="dc-time">{{ ago(devices[name].info.last_seen) }}</span>
|
||||
<span class="dc-time">{{ countdown(devices[name].info.last_seen) }}<a-icon v-if="refreshing" type="loading" style="font-size:10px;color:var(--accent)" /></span>
|
||||
</div>
|
||||
<div class="dc-bd" style="padding:4px 14px 8px;display:flex;align-items:center;justify-content:space-between">
|
||||
<div style="display:flex;align-items:center;gap:6px">
|
||||
@@ -299,10 +299,12 @@ Vue.component('cpu-section',{
|
||||
props:['cpu','info','isOn'],
|
||||
template:`<div class="sec">
|
||||
<div class="sec-tt">CPU · <span class="hl">{{ model }}</span></div>
|
||||
<div class="info-row"><span class="label">核心/线程</span><span class="value">{{ pc }} / {{ lc }}</span>
|
||||
<span class="label" style="margin-left:auto">温度</span><span class="value" :style="{color:tempColor,marginLeft:'4px'}">{{ tmpStr }}</span>
|
||||
<span class="label" style="margin-left:8px">频率</span><span class="value" style="margin-left:4px">{{ freq }} MHz</span></div>
|
||||
<a-progress :percent="pct" :stroke-color="barColor" :stroke-width="5" size="small" :format="fmtPct" />
|
||||
<div style="display:flex;align-items:center;gap:8px">
|
||||
<a-progress :percent="pct" :stroke-color="barColor" :stroke-width="6" size="small" :format="fmtPct" style="flex:1;min-width:0" />
|
||||
<span class="value" style="font-size:10px;white-space:nowrap;color:var(--dim)">{{ pc }}/{{ lc }}</span>
|
||||
<span class="value" :style="{color:tempColor,fontSize:'10px',whiteSpace:'nowrap'}">{{ tmpStr }}</span>
|
||||
<span class="value" style="font-size:10px;white-space:nowrap;color:var(--dim)">{{ freq }}MHz</span>
|
||||
</div>
|
||||
</div>`,
|
||||
computed:{
|
||||
model:function(){return this.cpu.model||(this.info&&this.info.cpu_model)||'Unknown'},
|
||||
@@ -321,16 +323,19 @@ Vue.component('cpu-section',{
|
||||
Vue.component('mem-section',{
|
||||
props:['mem','isOn'],
|
||||
template:`<div class="sec"><div class="sec-tt">MEMORY</div>
|
||||
<div v-if="mem.total_bytes"><div class="info-row"><span class="label">{{ used }} / {{ total }}</span><span class="value" :style="{color:barColor}">{{ pct }}%</span></div>
|
||||
<a-progress :percent="pct" :stroke-color="barColor" :stroke-width="5" size="small" :format="fmtPct" /></div>
|
||||
<div v-else style="font-size:9px;color:var(--dim)">无数据</div></div>`,
|
||||
<div v-if="mem.total_bytes" style="display:flex;align-items:center;gap:8px">
|
||||
<a-progress :percent="pct" :stroke-color="barColor" :stroke-width="6" size="small" :format="fmtPct" style="flex:1;min-width:0" />
|
||||
<span class="value" style="font-size:10px;white-space:nowrap;color:var(--dim)">{{ used }}/{{ total }}</span>
|
||||
<span class="value" :style="{color:barColor,fontSize:'10px',whiteSpace:'nowrap'}">{{ pct }}%</span>
|
||||
</div>
|
||||
<div v-else style="font-size:10px;color:var(--dim)">无数据</div></div>`,
|
||||
computed:{total:function(){return fmtB(this.mem.total_bytes)},used:function(){return fmtB(this.mem.used_bytes)},pct:function(){return Math.round(this.mem.percent||0)},barColor:function(){return pColor(this.pct)}},
|
||||
methods:{fmtPct:function(v){return v+'%'}}
|
||||
});
|
||||
|
||||
Vue.component('gpu-section',{
|
||||
props:['gpus','expandedGpu'],
|
||||
template:`<div class="sec"><div class="sec-tt">GPU · <span class="hl">{{ gpus.length }} 张</span></div>
|
||||
template:`<div class="sec"><div class="sec-tt">GPU · <span class="hl">{{ gpus.length }} 张</span><span style="margin-left:auto;font-size:9px;color:var(--text);font-family:var(--mono)">{{ totalPower }} W</span></div>
|
||||
<div class="gpu-grid"><div class="gpu-block" :class="{'gpu-active':expandedGpu===i}" v-for="(g,i) in gpus" :key="i">
|
||||
<a-popover trigger="click" placement="bottom" :visible="expandedGpu===i" @visibleChange="onVis(i,$event)" overlayClassName="gpu-popover" :getPopupContainer="getPopContainer">
|
||||
<template slot="content"><div class="gpu-pop-body">
|
||||
@@ -352,10 +357,13 @@ Vue.component('gpu-section',{
|
||||
<div class="gb-top"><span class="gb-temp" :style="{color:tmpColor(g)}">{{ tmpStr(g) }}</span>
|
||||
<span class="gb-fan"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v4m0 12v4m-7.07-3.93l2.83-2.83m8.48-8.48l2.83-2.83M2 12h4m12 0h4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83"/></svg>{{ fanStr(g) }}</span></div>
|
||||
<div class="gb-bar"><div class="gb-fill" :style="{width:(g.load_percent||0).toFixed(0)+'%',background:pColor(g.load_percent||0)}"></div><span class="gb-pct">{{ (g.load_percent||0).toFixed(0) }}%</span></div>
|
||||
<div class="gb-info"><span :style="{color:pColor(vramPct(g))}">{{ vramPct(g).toFixed(0) }}%</span><span style="color:var(--dim)">{{ vramStr(g) }}</span></div>
|
||||
<div class="gb-info"><span style="color:var(--dim)">{{ vramStr(g) }}</span><span style="color:var(--text)">{{ Math.round(g.power||0) }}W</span></div>
|
||||
</div>
|
||||
</a-popover>
|
||||
</div></div></div>`,
|
||||
computed:{
|
||||
totalPower:function(){var t=0;for(var i=0;i<this.gpus.length;i++)t+=this.gpus[i].power||0;return Math.round(t)}
|
||||
},
|
||||
methods:{
|
||||
pColor:pColor, tmpStr:function(g){var t=(g||{}).temperature||0;return t>0?t.toFixed(0)+'°':'—'},
|
||||
tmpColor:function(g){var t=(g||{}).temperature||0;return t>=85?'#ff4060':t>=70?'#ffb020':'#e2e6ef'},
|
||||
@@ -421,7 +429,7 @@ function buildChartSvg(hist){
|
||||
|
||||
new Vue({
|
||||
el:'#app',
|
||||
data:function(){return{loginForm:null,loginLoading:false,loginErr:'',loginConn:'',authed:false,wsOnline:false,devices:{},expandedGpu:null,clock:'',ws:null}},
|
||||
data:function(){return{loginForm:null,loginLoading:false,loginErr:'',loginConn:'',authed:false,wsOnline:false,devices:{},expandedGpu:null,clock:'',ws:null,refreshing:false}},
|
||||
created:function(){this.loginForm=this.$form.createForm(this)},
|
||||
computed:{
|
||||
deviceCount:function(){return Object.keys(this.devices).length},
|
||||
@@ -436,7 +444,19 @@ new Vue({
|
||||
methods:{
|
||||
getLive:function(name){var e=this.devices[name];if(!e||!e.live)return{};var l=e.live;if(typeof l==='string')try{l=JSON.parse(l)}catch(ex){}return l||{}},
|
||||
isPoolOnline:function(name){var e=this.devices[name];return e&&e.mining&&e.mining.status==='online'},
|
||||
ago:ago, toggleGpu:function(i){this.expandedGpu=i},
|
||||
ago:ago,
|
||||
showRefresh:function(){var self=this;this.refreshing=true;setTimeout(function(){self.refreshing=false},500)},
|
||||
countdown:function(iso){
|
||||
if(!iso)return'—';
|
||||
var d=new Date(iso);if(isNaN(d))return'—';
|
||||
var s=Math.floor((Date.now()-d.getTime())/1000);
|
||||
if(s<0)return'刚刚';
|
||||
if(s<60)return s+'秒前';
|
||||
if(s<3600)return Math.floor(s/60)+'分钟前';
|
||||
if(s<86400)return Math.floor(s/3600)+'小时前';
|
||||
return Math.floor(s/86400)+'天前';
|
||||
},
|
||||
toggleGpu:function(i){this.expandedGpu=i},
|
||||
deleteDevice:function(n){var self=this;this.$confirm({title:'确定删除 '+n+' 的设备记录?',onOk:function(){if(self.ws&&self.ws.readyState===1)self.ws.send(JSON.stringify({action:'delete',machine:n}))}})},
|
||||
handleLogin:function(e){e.preventDefault();var self=this;this.loginForm.validateFields(function(err,values){if(err)return;self.loginLoading=true;self.loginErr='';self.loginConn='';localStorage.setItem('mm_id',values.miner_id);localStorage.setItem('mm_pw',values.password);self.connectWs(values.miner_id,values.password)})},
|
||||
sendAuth:function(mid,pw){if(this.ws&&this.ws.readyState===WebSocket.OPEN)this.ws.send(JSON.stringify({type:'auth',miner_id:mid,password:pw}))},
|
||||
@@ -453,9 +473,9 @@ new Vue({
|
||||
case'auth_required':this.loginConn='服务已连接,正在认证...';var mid=this.loginForm.getFieldValue('miner_id')||localStorage.getItem('mm_id');var pw=this.loginForm.getFieldValue('password')||localStorage.getItem('mm_pw');this.sendAuth(mid,pw);break;
|
||||
case'auth_ok':this.authed=true;this.loginLoading=false;break;
|
||||
case'auth_fail':this.loginErr=msg.msg||'设备ID或密码错误';this.loginLoading=false;localStorage.removeItem('mm_pw');break;
|
||||
case'snapshot':this.devices={};if(msg.devices)this.devices=Object.assign({},msg.devices);if(this.authed)this.wsOnline=true;break;
|
||||
case'device':var prev=this.devices[msg.machine];this.$set(this.devices,msg.machine,msg.device);if(prev&&prev.hash_history&&(!msg.device.hash_history||!msg.device.hash_history.length))this.$set(this.devices[msg.machine],'hash_history',prev.hash_history);break;
|
||||
case'mining':var mi=msg.mining||{};var oAt=mi.opened_at>0?new Date(mi.opened_at).toISOString():null;var lAc=mi.last_active>0?new Date(mi.last_active).toISOString():null;if(this.devices[msg.machine]){this.$set(this.devices[msg.machine],'mining',mi);if(msg.hash_history)this.$set(this.devices[msg.machine],'hash_history',msg.hash_history);var dInf=this.devices[msg.machine].info||{};if(!dInf.first_seen&&oAt)dInf.first_seen=oAt;if(!dInf.last_seen&&lAc)dInf.last_seen=lAc;this.$set(this.devices[msg.machine],'info',dInf)}else{this.$set(this.devices,msg.machine,{info:{machine_name:msg.machine,first_seen:oAt,last_seen:lAc},online:false,mining:mi,hash_history:msg.hash_history})}break;
|
||||
case'snapshot':this.devices={};if(msg.devices)this.devices=Object.assign({},msg.devices);if(this.authed)this.wsOnline=true;this.showRefresh();break;
|
||||
case'device':var prev=this.devices[msg.machine];this.$set(this.devices,msg.machine,msg.device);if(prev&&prev.hash_history&&(!msg.device.hash_history||!msg.device.hash_history.length))this.$set(this.devices[msg.machine],'hash_history',prev.hash_history);this.showRefresh();break;
|
||||
case'mining':var mi=msg.mining||{};var oAt=mi.opened_at>0?new Date(mi.opened_at).toISOString():null;var lAc=mi.last_active>0?new Date(mi.last_active).toISOString():null;if(this.devices[msg.machine]){this.$set(this.devices[msg.machine],'mining',mi);if(msg.hash_history)this.$set(this.devices[msg.machine],'hash_history',msg.hash_history);var dInf=this.devices[msg.machine].info||{};if(!dInf.first_seen&&oAt)dInf.first_seen=oAt;if(!dInf.last_seen&&lAc)dInf.last_seen=lAc;this.$set(this.devices[msg.machine],'info',dInf)}else{this.$set(this.devices,msg.machine,{info:{machine_name:msg.machine,first_seen:oAt,last_seen:lAc},online:false,mining:mi,hash_history:msg.hash_history})}this.showRefresh();break;
|
||||
case'remove':this.$delete(this.devices,msg.machine);this.expandedGpu=null;break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user