Commit 8abfbaf1 authored by xhx's avatar xhx

feat:树莓派导入

parent 899c5c19
......@@ -2,5 +2,5 @@ NODE_ENV="development"
#VUE_APP_URL="http://172.16.100.59:8090"
VUE_APP_URL="http://172.16.100.59:8092"
VUE_APP_CHAIN="http://172.16.100.59:8801"
#VUE_APP_CHAIN="https://mainnet.bityuan.com/api"
VUE_APP_AIRDROP = "http://172.16.100.59:8091"
\ No newline at end of file
VUE_APP_AIRDROP = "http://172.16.100.59:8091"
VUE_APP_NODE=http://118.24.145.138:8801
\ No newline at end of file
NODE_ENV="production"
VUE_APP_URL="http://47.243.139.223:8000"
VUE_APP_NODE=http://118.24.145.138:8801
VUE_APP_CHAIN="https://mainnet.bityuan.com/api"
\ No newline at end of file
NODE_ENV='development'
VUE_APP_URL="http://172.16.100.59:8090"
#VUE_APP_URL="http://172.16.100.59:8092"
VUE_APP_CHAIN="http://172.16.100.59:8801"
\ No newline at end of file
#VUE_APP_CHAIN="http://172.16.100.59:8801"
VUE_APP_CHAIN="http://172.16.100.247:8801"
VUE_APP_NODE=http://118.24.145.138:8801
\ No newline at end of file
......@@ -30,7 +30,8 @@
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^9.1.2",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
"vuex": "^3.4.0",
"whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.18.0",
......
<template>
<ul class="wallet-status-component" :class="iconClass">
<li>
<img :src="require(`@/assets/node${isButton}_normal@2x.png`)"/>
<div class="desc active">节点状态</div>
</li>
<!-- showLockStatusDialog -->
<li @click="lockStatusHandler">
<div v-if="!walletStatus.isWalletLock">
<img :src="require(`@/assets/full_unlock${isIcon?'_icon':'_button'}@2x.png`)" alt />
<div class="desc active">全解锁</div>
</div>
<div v-else-if="walletStatus.isWalletLock && walletStatus.isTicketLock">
<img :src="require(`@/assets/all_lock${isIcon?'_icon':'_button'}@2x.png`)" alt />
<div class="desc">全锁定</div>
</div>
<div v-else>
<img :src="require(`@/assets/mine_unlock${isIcon?'_icon':'_button'}@2x.png`)" alt />
<div class="desc active" >挖矿解锁</div>
</div>
</li>
<li>
<img :src="require(`@/assets/time${isButton}_normal@2x.png`)" alt />
<div class="desc" :class="[!timeSync?'active':'']">时间同步</div>
</li>
<li @click="showHeightHandler">
<img :src="require(`@/assets/block${isButton}_normal@2x.png`)" v-if="blockSync" alt />
<img :src="require(`@/assets/block${isButton}@2x.png`)" v-else alt />
<div class="desc" :class="[blockSync?'active':'']" >
<!-- blockanmation -->
<div>区块同步</div>
<!-- <div v-if="!blockSync">
{{`(${peerHeight})`}}
</div> -->
<!-- {{`(${Math.floor(peerHeight/allHeight * 100)}/100)`}}</div> -->
</div>
</li>
<!-- autoMiningHandler -->
<li @click="autoMiningStatusHandler">
<img :src="require(`@/assets/ticket${isButton}@2x.png`)" v-if="walletStatus && !walletStatus.isAutoMining" alt />
<img :src="require(`@/assets/ticket${isButton}_normal@2x.png`)" v-else alt />
<div class="desc" :class="[(walletStatus && !walletStatus.isAutoMining)?'':'active']">自动购票</div>
</li>
<div v-if="!isIcon" class="block-height" :class="[blockSync?'active':'']">{{`(${peerHeight})`}}</div>
</ul>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
isIcon: {
type: Boolean,
default: false
},
walletStatus: {
type: Object as any,
required: true
},
timeSync: {
type: Object as any,
},
blockSync: {
type: Boolean,
required: true
},
peerHeight: {
type: Number,
},
allHeight: {
type: Number
}
},
computed: {
isButton(){
return this.isIcon?'':'_button'
},
iconClass(){
return {
icon:this.isIcon
}
}
},
methods: {
lockStatusHandler() {
this.$emit('showLockStatusDialog')
},
autoMiningStatusHandler() {
this.$emit('autoMiningHandler')
},
showHeightHandler() {
this.$emit('showHeightHandler')
}
}
})
</script>
<style lang="scss" scoped>
@keyframes hue {
from {
color: rgba(255, 255, 255, 0.4);
}
to {
color: gray;
}
}
ul.wallet-status-component{
display: flex;
display: grid;
grid-template-columns: repeat(5,1fr);
place-content: space-between;
padding: 0.34rem 0;
// justify-content: space-between;
.block-height{
grid-column: 3 / span 3;
&.active{
color: rgba(230, 88, 132, 0.7);
}
}
.action{
width: 100%;
height:auto;
background: #eeeeee;
}
.blockanmation {
animation: hue 3s linear infinite;
}
li {
flex-direction: column;
justify-content: center;
text-align: center;
overflow: hidden;
img{
width: 0.8rem;
height: auto;
}
div.desc {
font-size: 0.24rem;
&.active {
color: rgba(230, 88, 132, 0.7);
}
}
}
&.icon{
padding:0;
li{
display: inline-block;
margin-right: 0.2rem;
img{
width: 0.3rem;
height: auto;
}
.desc{
display: none;
}
}
}
}
</style>
\ No newline at end of file
// 游戏节点
// export const gameNodeURL = 'http://47.92.120.76:8903';
export const gameNodeURL = 'http://192.168.100.139:8801';
// 合约名称
export const contractName = 'user.p.fzmtest.powerball';
// 充币地址
export const rechargeAddr = '19P8bhxiBkBVbVojgYRoQcWVWXMtksf76q';
// 提币地址
export const withdrawalAddr = '1DyJrTktyFxBjzJLg5oPpCPH4RZZiaJQJL';
// 游戏id
export const gameLotteryId = '0x0cace9c04e0e044dd630dd88d2a20243360bc1a6413a5ce4015d07099387c1ac';
// 冲提现地址
export const rechargeWithdrawUrl = 'http://47.74.190.154/gameCashier';
//树莓派设备外网统计服务
export const paiOuterNetURL = process.env.VUE_APP_SERVER
export const paiDeviceManager = process.env.VUE_APP_DEVICEMANAGER
export const airDropURL = process.env.VUE_APP_AIRDROP
export const CONTRAC_ADDRESS = '16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp' // 合约地址
export const APP_NAME = 'YUAN-miner' // 应用名称
export const TICKET_PRICE = 3000 // 3000bty
export const withhold = -1 // 交易组是否代扣 代扣:1 不代扣:-1
......@@ -8,9 +8,9 @@ import '@/style.css'
import vconsole from 'vconsole'
if (process.env.NODE_ENV === 'development') {
// if (process.env.NODE_ENV === 'development') {
new vconsole()
}
// }
Vue.config.productionTip = false
......
......@@ -31,6 +31,11 @@ const routes: Array<RouteConfig> = [
name: 'noPage',
component: () => import(/* webpackChunkName: "about" */ '../views/NoPage/index.vue')
},
{
path: '/nodePage',
name: 'nodePage',
component: () => import(/* webpackChunkName: "about" */ '../views/NodePage/List/index.vue')
},
]
const router = new VueRouter({
......
import { callDeviceManagerAPI } from '@/service/service';
/**
* @description 重置钱包
* @param ip
*/
export function resetWallet(ip = ''){
return callDeviceManagerAPI({
},'resetwallet',ip);
}
/**
* @description 节点是否在升级
* @param ip
*/
export async function nodeUpdate(ip = ''){
const {status} = await callDeviceManagerAPI({
},'nodeupdate',ip);
if(status){
throw '正在升级'
}
}
/**
* @description 安全关闭节点
* @param ip
*/
export function closeNode(ip = ''){
return callDeviceManagerAPI({
},'closenode',ip);
}
/**
* @description 重置节点
* @param ip
*/
export function reset(ip = ''){
return callDeviceManagerAPI({
},'reset',ip);
}
/**
* @description 查询节点版本
* @param ip
*/
export function version(ip = ''){
return callDeviceManagerAPI({
},'version',ip);
}
/**
* @description 查询守护程序版本
* @param ip
*/
export function paiVersion(ip = ''){
return callDeviceManagerAPI({
},'paiversion',ip);
}
/**
* @description 更新守护进程
* @param version
* @param ip
*/
export function updatePai(version = '' ,ip = ''){
return callDeviceManagerAPI({
version
},'updatepai',ip);
}
/**
* @description 节点更新到新版本
* @param ip
*/
export function updateNode(ip = ''){
return callDeviceManagerAPI({
},'updatenode',ip);
}
export function updateDetail(ip = ''){
return callDeviceManagerAPI({
},'updatedetail',ip);
}
export function downloadpercent(ip = ''){
return callDeviceManagerAPI({
},'dpercent',ip)
}
export function nodeInfo(ip = ''){
return callDeviceManagerAPI({
},'nodeinfo',ip)
}
export function serverstatus(ip = ''){
return callDeviceManagerAPI({},'serverstatus',ip)
}
/**
* 代解锁
* @param password 钱包密码
* @param ip 节点ip
*/
export function escrowPassword(password:string,ip = ''){
return callDeviceManagerAPI({password},'escrowpassword',ip)
}
/**
* 反馈接口
* @param description
* @param ip
*/
export function feedback(description:string,addr:string,ip = ''){
return callDeviceManagerAPI({description,addr},'feedback',ip)
}
/**
* 最新反馈是否完成查询接口
* @param ip
*/
export function isComplete(ip = ''){
return callDeviceManagerAPI({},'iscomplete',ip);
}
import Rpc from '@33cn/chain33-rpc-api'
import { Toast } from 'vant';
export const rpc = new Rpc(process.env.VUE_APP_NODE,function(res:any){
if(res.error){
return Promise.reject(res.error);
}
return res.result
},function(err:any){
Toast(err.message || err);
})
\ No newline at end of file
import axios from "axios";
import HttpProvider from "@/utils/httpProvider";
import {gameNodeURL} from '@/constance/config';
// const baseUrl = '/api'
......@@ -9,3 +11,38 @@ export const request = function(baseUrl: string) {
})
}
export const httpProvider: HttpProvider = new HttpProvider(gameNodeURL);
export function callDeviceManagerAPI(params:any = {},apiName='',url=''){
return httpProvider.doFetch({
url:`http://${url}:8803/pai/${apiName}`,
postdata: {
...params
}
}).then((res: any) => {
console.log('矿机接口->',res)
if(res.code === 200){
return res.data;
}else if(res.code === 400){
return Promise.reject('请求参数错误')
}else if (res.code === 5000) {
return Promise.reject('安全关闭节点,请重启矿机\n其他操作导致请咨询客服')
} else if (res.code === 5001) {
return Promise.reject('安全关闭节点,请重启矿机\n其他操作导致请咨询客服') // 树莓派上出错了,可能缺少某些文件之类的
} else if (res.code === 5002) {
return Promise.reject('正在更新')
} else if (res.code === 5004) {
return Promise.reject('网络错误, 请检查您的网络')
} else if(res.code === 5013){
return Promise.reject(res.data);
}else if(res.code === 5014){
return Promise.reject('未解决');
} else if(res.code === 5015){
return Promise.reject(res.msg);
}else{
console.log('矿机错误',res);
throw '矿机错误';
}
});
}
import { rpc } from '@/service/rpc';
import errMsg from '@33cn/chain33errori18n'
export async function saveSeedService(seed:string,passwd:string,url= ''):Promise<any>{
const saveSeedRsp = await rpc.saveSeed(seed,passwd,url)
console.log('saveSeedRsp',saveSeedRsp);
if(!saveSeedRsp.isOK) throw errMsg(saveSeedRsp.msg)
return saveSeedRsp;
}
export async function unLockService(passwd:string,walletorticket = true,timeout = 0,url = ''){
const unlockRsp = await rpc.unlock(passwd,walletorticket,timeout,url);
console.log('unlockService->',unlockRsp)
if(!unlockRsp.isOK) throw errMsg(unlockRsp.msg);
return unlockRsp;
}
export async function newAccountService(label= '',url =''){
const newAccountRsp = await rpc.newAccount(label,url);
console.log('newAccountService->',newAccountRsp)
return newAccountRsp;
}
export async function createAccount(config:any,url = ''){
console.log('createAccount params->',config)
config = {...{
walletorticket: false,// 默认钱包全解锁
timeout:0 ,// 解锁时间,永久解锁
label:'' // 账号label
},...config};
const { seed, passwd, walletorticket ,timeout ,label} = config
await saveSeedService(seed,passwd,url);
await unLockService(passwd,walletorticket,timeout,url);
await newAccountService(label,url);
}
\ No newline at end of file
......@@ -6,4 +6,7 @@ export const getCurrentBTYAddress = (params: any, fn?: Function) => _jsBridge.ge
export const signGroup = (params: any, fn?: Function) => _jsBridge.signTxGroup(params, fn)
export const closeWebview = () => _jsBridge.closeCurrentWebview()
export const getDeviceId = (params: any, fn?: Function) => _jsBridge.getDeviceId(params, fn)
export const getScan = (params: any, fn?: Function) => _jsBridge.scanQRCode(params, fn)
\ No newline at end of file
export const getScan = (params: any, fn?: Function) => _jsBridge.scanQRCode(params, fn)
export const getDeviceList = (params: any, fn?: Function) => _jsBridge.getDeviceList (params, fn)
export const getWifiName = (params: any, fn?: Function) => _jsBridge.getCurrentWifi (params, fn)
export const importSeed = (params: any, fn?: Function) => _jsBridge.importSeed (params, fn)
\ No newline at end of file
import { rpc } from "@/service/rpc";
import { nodeUpdate } from "@/service/device";
export const getNodeStatus = async (deviceInfo:any) => {
console.log('deviceInfo',deviceInfo)
const {ip} = deviceInfo;
const url = `http://${ip}:8801`
const nodeStatus = {isBind:false,...deviceInfo}
try {
await nodeUpdate(ip);
const allResult:any = await Promise.all([
rpc.getWalletStatus(url),
rpc.isSync(url),
rpc.getTicketCount(url),
rpc.getAccounts(false,url),
rpc.getPeerInfo(url),
]);
const [ walletStatus,
isSync,
ticketCount,
accounts,
peersInfo] = allResult;
console.log(walletStatus,'walletStatus-------------',allResult)
if(!walletStatus.isHasSeed){
return nodeStatus
// throw new Error('ErrSeedNotExist')
}
console.log('accounts',accounts);
const account = accounts && accounts.wallets &&
accounts.wallets.find((wallet: any) => {
return wallet.label === 'YUAN-miner节点'
});
console.log('account',account);
if(!account){
// throw new Error('没有导入钱包')
return nodeStatus
}
return {...nodeStatus,...{isBind:true},...{walletStatus,isSync,ticketCount,accounts,peersInfo}}
// return Object.assign({},{walletStatus,isSync,ticketCount,accounts,peersInfo},{isBind:true},deviceInfo);
} catch (err: any) {
console.log(err.message||err,'-->err')
if(['ErrAccountNotExist'].includes(err)){
return nodeStatus;
}
if(['ErrChannelClosed'].includes(err) || ['Failed to fetch'].includes(err.message)){
return {err:'节点已关闭',...{nodeStatus}}
}
return {...{err},...nodeStatus}
}
}
\ No newline at end of file
import 'whatwg-fetch';
interface ResponseError extends Error {
response: any;
}
export default class HttpProvider {
private errorHandler: any;
private url: any;
constructor(url: string, errorHandler: any = null) {
this.errorHandler = errorHandler;
this.url = url;
this.setUrl.bind(this);
this.doFetch.bind(this);
}
public setUrl(url: string) {
this.url = url;
}
public doFetch(config: any) {
const {
httpHeaders = {},
postdata,
} = config;
let {url} = config;
if (!url) {
url = this.url;
}
const headers = {
// 'Content-Type': 'text/plain',
'Content-Type': 'application/json',
...httpHeaders,
};
const reqConfig: RequestInit = {
method: 'POST',
headers,
redirect: 'follow',
};
if (postdata) {
reqConfig.body = JSON.stringify(postdata);
}
return fetch(url, reqConfig)
.then(this.checkStatus)
.then((resp) => resp.json())
.catch((e) => {
if (this.errorHandler) {
this.errorHandler(e);
} else {
throw e;
}
});
}
private checkStatus(response: any) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
const error: ResponseError = new Error(response.statusText) as ResponseError;
error.response = response;
throw response.statusText;
// throw error;
}
}
}
import {importSeed} from '@/utils/bridge'
export function passwdInputProxy(fn:Function){
return new Proxy(fn,{
async apply(target,thisBind,args){
try{
importSeed('');
}catch(err){
if(err === '取消支付'){
throw '取消'
}
throw err;
}
return Reflect.apply(target,thisBind,args)
}
})
}
\ No newline at end of file
......@@ -132,6 +132,9 @@ export default Vue.extend({
created() {
this.getFee()
this.getInfo()
},
beforeDestroy() {
Toast.clear()
}
})
</script>
......
......@@ -84,8 +84,10 @@ export default Vue.extend({
getUserInfo().then(res => {
const type = res.data.data.type + ''
const status = res.data.data.status + ''
if (type === '1' || type === '2') {
if (type === '2') {
this.$router.replace({ path: '/noPage', query: { type: type }})
} else if (type === '1') {
this.$router.replace({ path: '/nodePage' })
} else if (status === '1') {
this.$router.replace({ path: '/noPage', query: { status }})
}
......
<template>
</template>
\ No newline at end of file
<template>
<div class="device-item-component">
<div class="device-unlink" v-if="err">
<div class="device-info" >
<p>设备编号{{deviceSerial}}</p>
<p>{{err.message || err}}</p>
</div>
</div>
<div v-else>
<div tag="div" class="device-linked" v-if="isBind" @click.capture="routeToMiningDetailHandler">
<!-- <img
class="mining"
:class="{clock:isMining}"
src="@/assets/mining@2x.png"
/> -->
<div class="device-info">
<p class="device-num">
<img src="@/assets/image/device@2x.png" alt />
设备编号{{deviceSerial}}
</p>
<p class="mining-address">挖矿地址:{{paiWalletAddress | shortAddress}}</p>
<p>挖矿数量(BTY)</p>
<p class="miningBTY">{{miningBtyCount}}</p>
</div>
<div class="node-status">
<wallet-status :isIcon="true" :walletStatus="walletStatus" :blockSync="blockSync"></wallet-status>
<p style="text-align:right;">
<span>{{walletLabel}}</span>
<span>{{miningStatusStr}} <img src="@/assets/image/rotate.png" style="width:.4rem;height:.16rem;" :class="{rotate:isMining}" alt=""></span>
</p>
</div>
</div>
<div class="device-unlink" v-else>
<div class="device-info">
<p>设备编号</p>
<p>{{deviceSerial}}</p>
</div>
<div class="img" @click="link"></div>
</div>
</div>
<div class="feedback" v-if="isfeedback" >
<div class="feedbackBtn" @click.capture="feedback">反馈此设备</div>
</div>
<div class="more" v-if="!err">
<div @click="showMenuHandler" class="caozuo"></div>
<!-- <img src="@/assets/more.png" class="caozuo" alt="更多" @click="showMenuHandler"> -->
<ul class="menu" v-show="showMenu">
<li class="btn" @click.stop.capture="resetWallet" v-if="isBind">重置钱包</li>
<li class="btn" @click.stop.capture="safeClose">安全关闭</li>
<li class="btn" @click.stop.capture="feedback">反馈</li>
</ul>
</div>
</div>
</template>
<script lang='ts'>
import Vue, { PropType } from 'vue';
import WalletStatus from '@/components/WalletStatus.vue';
interface IDeviceInfo {
serial: string; //设备唯一序列号
ip: string; //树莓派设备局域网ip
isBind: boolean;
ticketCount: any;
accounts: any;
isSync: any;
walletStatus: any;
peersInfo: any;
err:any;
}
export default Vue.extend({
props: {
deviceInfo: {
type: Object as PropType<IDeviceInfo>,
required: true
},
isfeedback: {
type: Boolean,
required: false,
default:false
}
},
components: {
WalletStatus
},
data() {
return {
showMenu: false,
paiWalletAddress: '',
isMining: false,
err: '',
isBind: false,
ticketCount: '' as any,
accounts: {} as any,
isSync: '' as any,
walletStatus: '' as any,
peersInfo: '' as any,
}
},
computed: {
deviceSerial(): string {
return this.deviceInfo.serial || '';
},
miningStatusStr(): string {
if (this.isMining) {
return '正在挖矿';
} else {
return '未挖矿';
}
}
},
methods: {
resetWallet() {
this.$emit('reset-wallet',{
ip: this.deviceInfo.ip,
mineAddress: this.paiWalletAddress,
deviceSerial: this.deviceSerial,
})
},
safeClose() {
this.$emit('safe-close', {
ip: this.deviceInfo.ip,
mineAddress: this.paiWalletAddress,
})
},
feedback() {
this.$emit('feed-back', {
ip: this.deviceInfo.ip,
mineAddress: this.paiWalletAddress,
deviceSerial:this.deviceSerial,
})
},
showMenuHandler(){
this.showMenu = !this.showMenu;
},
link() {
this.$emit('link-device', {
ip: this.deviceInfo.ip,
deviceSerial: this.deviceSerial
})
},
routeToMiningDetailHandler() {
if (this.showMenu) {
this.showMenu = false
}
this.$emit('route-to', {
ip: this.deviceInfo.ip,
mineAddress: this.paiWalletAddress,
deviceSerial:this.deviceSerial,
})
}
},
watch: {
'deviceInfo': {
immediate: true,
deep: true,
handler(val: IDeviceInfo, oldVal: IDeviceInfo) {
this.isBind = val.isBind;
this.walletStatus = val.walletStatus;
this.isSync = val.isSync;
this.ticketCount = val.ticketCount;
this.peersInfo = val.peersInfo;
this.accounts = val.accounts;
this.err = val.err;
}
}
}
})
</script>
<style scoped lang="scss">
.device-item-component {
position: relative;
padding: 0.4rem 0.24rem 0.52rem;
margin-bottom: 0.2rem;
border-radius: 0.2rem;
overflow: hidden;
background: rgba(48, 51, 91, 0.08);
transition: height 1s;
.feedback{
position: absolute;
left:0;
right:0;
top:0;
bottom: 0;
z-index: 3;
display: flex;
justify-content: center;
align-items: center;
background: rgba(48, 51, 91, 0.3);
.feedbackBtn{
padding: .3rem;
font-size: .24rem;
border-radius: .3rem;
background: gray;
color:#FFFFFF;
}
}
.more{
position: absolute;
right:0;
top:0;
text-align: right;
.caozuo{
box-sizing: content-box;
width:.1rem;
height: .4rem;
padding:.34rem;
padding-left:.6rem;
background: url('../../../assets/image/more.png');
background-repeat: no-repeat;
background-size: .1rem auto;
background-position: .6rem .34rem;
}
.menu{
position: fixed;
width:1.9rem;
right:.34rem;
margin-right: .34rem;
background: gray;
color:#FFFFFF;
border-radius: .12rem;
li.btn{
height:.72rem;
line-height: .72rem;
padding: 0 .34rem;
text-align: center;
&:active{
color: gray;
}
}
}
}
.device-unlink {
display: flex;
align-items: center;
justify-content: space-between;
.device-info {
display: flex;
flex-direction: column;
justify-content: space-between;
color: rgba(48, 51, 91, 1);
font-size: 0.36rem;
line-height: 0.44rem;
p:first-child {
font-size: 0.24rem;
line-height: 0.34rem;
margin-bottom: 0.3rem;
color: rgba(48, 51, 91, 0.6);
}
}
div.img {
width: 0.72rem;
height: 0.72rem;
background: url("../../../assets/image/link@2x.png");
background-size: contain;
margin-top: .5rem;
&:active {
background: url("../../../assets/image/linked@2x.png");
background-size: contain;
}
}
}
.device-linked {
position: relative;
img.mining {
position: absolute;
right: 0.5rem;
top: -0.4rem;
width: 0.58rem;
height: 2.54rem;
}
.device-info {
font-size: 0.24rem;
font-family: PingFangSC;
font-weight: 400;
color: rgba(48, 51, 91, 0.6);
line-height: 0.34rem;
.device-num {
display: flex;
align-items: center;
font-size: 0.28rem;
font-family: PingFangSC;
font-weight: 600;
color: rgba(48, 51, 91, 1);
line-height: 0.4rem;
img {
width: 0.42rem;
margin-right: 0.16rem;
}
}
.mining-address {
margin: 0.24rem 0;
}
.miningBTY {
margin: 0.3rem 0 0.6rem 0;
font-size: 0.6rem;
font-family: DIN;
font-weight: bold;
color: rgba(48, 51, 91, 1);
line-height: 0.72rem;
}
}
.node-status {
display: flex;
justify-content: space-between;
align-items: flex-end;
p {
display: flex;
flex-direction: column;
font-size: 0.24rem;
font-family: PingFangSC;
font-weight: 400;
color: rgba(48, 51, 91, 1);
}
}
}
}
.clock {
-webkit-animation: go 1.5s ease-in-out alternate infinite;
-moz-animation: go 1.5s ease-in-out alternate infinite;
animation: go 1.5s ease-in-out alternate infinite;
}
@keyframes go {
0% {
-webkit-transform: rotate(15deg);
-webkit-transform-origin: top center;
-moz-transform: rotate(15deg);
-moz-transform-origin: top center;
transform: rotate(15deg);
transform-origin: top center;
}
100% {
-webkit-transform: rotate(-15deg);
-webkit-transform-origin: top center;
-moz-transform: rotate(-15deg);
-moz-transform-origin: top center;
transform: rotate(-15deg);
transform-origin: top center;
}
}
@keyframes rotateKey {
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(369deg);
}
}
.rotate{
animation: rotateKey 1.5s linear infinite;
}
</style>
<template>
<div class="w-full min-h-screen">
<div v-if="!pageShow" class="min-h-screen flex items-center justify-center">
<div
class="
w-36
h-10
bg-card-text
rounded-lg
flex
justify-center
items-center
text-white
"
@click="pageShow = true"
>
导入
</div>
</div>
<div v-else>
<div
class="
w-full
h-24
flex flex-col
items-start
justify-center
px-8
text-white1 text-sm
"
>
<p class="w-full text-left">矿工地址:{{ 123 }}</p>
<p class="w-full flex justify-between items-center">
<span>当前WIFI:{{ wifiName }}</span>
<span
class="px-2 py-1 bg-brown3 rounded-lg"
role="button"
@click="scanDevicesHandler"
>查找设备</span
>
</p>
</div>
<div
class="w-full bg-white rounded-t-xl px-4"
style="height: calc(100vh - 96px)"
>
<p v-if="devices.length > 0" class="pt-3 text-sm mb-3">
已检测到以下设备,请选择需要绑定的{{ APP_NAME }}
</p>
<p v-if="devices.length == 0" class="pt-3 text-sm mb-3">
未检测到{{ APP_NAME }}设备
</p>
<device-item
v-for="(item, index) in devices"
:key="index"
:deviceInfo="item"
:isfeedback="isfeedback"
@feed-back="feedBackHandler"
@reset-wallet="resetWalletHandler"
@safe-close="safeCloseHandler"
@link-device="linkDevice"
@route-to="routeTo"
></device-item>
<!-- :style="isfeedback?{background:'rgba(48, 51, 91, 0.3)'}:{}" -->
<!-- <div class="feedback" :class="[isfeedback?'cancle':'']" @click.stop="feedback">{{isfeedback?'取消':'我要反馈'}}</div> -->
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { getDeviceList, getWifiName } from '@/utils/bridge'
import { getNodeStatus } from '@/utils/getDeviceInfo';
import DeviceItem from './DeviceItem.vue';
import { APP_NAME } from '@/constance/config';
import { closeNode, resetWallet, escrowPassword } from '@/service/device';
import { passwdInputProxy } from '@/utils/passwdProxy';
import { importSeed } from '@/utils/bridge';
import { createAccount } from '@/utils/account';
export default Vue.extend({
data() {
return {
pageShow: false,
wifiName: '',
devices: [
{isSync: true}
] as Array<any>,
isfeedback: false,
btyAddress: ''
}
},
computed: {
APP_NAME():string {
return APP_NAME
}
},
components: {
DeviceItem,
},
methods: {
scanDevicesHandler() {
this.paiList()
},
getWifi() {
getWifiName('', (res: string|{name: string}) => {
console.log(res)
if (typeof res === 'string') {
this.wifiName = JSON.parse(res)?.name
} else {
this.wifiName = res?.name
}
})
},
isEqualBtyAddress(mineAddress: string): boolean {
return this.btyAddress === mineAddress;
},
resetWalletHandler(params: any){
if (!this.isEqualBtyAddress(params.mineAddress)) {
this.$toast('请确认当前币钱包地址与YUAN-miner设备地址一致');
return;
}
let toast: any;
this.$dialog
.confirm({
title: '重置钱包',
message: '重置钱包将清除设备数据(完成可重新绑定设备)'
})
.then(async () => {
toast = this.$toast.loading({
duration: 0,
forbidClick: true,
message: '正在重置钱包,约30s...'
});
const resetWalletResult = await passwdInputProxy(resetWallet)(params.ip);
console.log('resetWalletResult', resetWalletResult);
setTimeout(() => {
this.$router.push({ name: 'index' });
toast.clear();
}, 30000);
})
.catch(err => {
toast.clear();
if (err !== 'cancel') {
this.$toast(err);
}
console.log('取消重置钱包', err);
});
},
safeCloseHandler(params: any){
this.$dialog
.confirm({
title: '安全关闭节点',
message: '确认安全关闭节点?'
})
.then(async () => {
await closeNode(params.ip)
this.$dialog
.alert({
title: '关闭成功',
// message: '矿机程序已经下载完成,请手动重启YUAN-miner设备',//请等待YUAN-miner程序重启
message: '节点关闭成功,请手动关闭YUAN-miner设备',
})
.then(() => {
// on close
this.$router.replace({name:'home'});
});
})
.catch(err => {
if (err !== 'cancel') {
this.$toast(err);
}
console.log('安全关闭节点', err);
});
},
feedBackHandler(params: any){
// if(this.isfeedback){
this.$dialog.confirm({
title:'反馈',
message:'确定需要反馈此台设备问题?'
}).then(() => {
this.$router.push({name:'feedback',params:{ip:params.ip,deviceSerial:params.deviceSerial}})
}).catch(err => {
if(err === 'cancel'){
console.log(err)
}
})
// }
},
routeTo(params: any) {
if (!this.isEqualBtyAddress(params.mineAddress)) {
this.$toast('请确认当前币钱包地址与YUAN-miner设备地址一致');
return;
}
this.$router.push({
name: 'miningDetail',
params: {
ip: params.ip,
deviceSerial:params.deviceSerial
}
});
},
// 从币钱包获取seed和密码,》 保存到树莓派 》 解锁树莓派钱包 》 新建树莓派account
async linkDevice({ ip,deviceSerial }: any) {
console.log('linkDeviceip:',ip)
let toast: any;
let url = `http://${ip}:8801`;
importSeed('', async (seedAndPasswd: any) => {
try {
if (typeof seedAndPasswd === 'string') {
seedAndPasswd = JSON.parse(seedAndPasswd)
}
console.log('seedandPasswd', seedAndPasswd);
const { seed, passwd } = seedAndPasswd;
toast = this.$toast.loading({
duration: 0,
forbidClick: true,
message: '正在导入钱包,请稍后...'
});
const label = 'YUAN-miner节点';
await createAccount({
seed,
passwd,
label
},url);
const savePasswd = await escrowPassword(seedAndPasswd.passwd, ip);
console.log('savePasswd', savePasswd);
// const applyAirDropResult = await applyAirDrop(deviceSerial,this.btyAddress);
// console.log('applyAirDropResult',applyAirDropResult);
toast.clear();
this.$toast.success('导入成功');
this.$router.push({ name: 'miningDetail', params: { ip ,deviceSerial}});
} catch (err: any) {
toast.clear();
console.log('导入出错啦', err);
this.$toast(err);
}
});
},
paiList(): any {
getDeviceList('', async(v: any) => {
console.log('deviceList', v)
if (typeof v === 'string') {
v = JSON.parse(v)
}
let tempDeviceList = [] as any
for (let i = 0; i < v.length; i++) {
let deviceData = await getNodeStatus(v[i])
tempDeviceList.push(deviceData)
}
console.log('tempDeviceList', tempDeviceList)
this.devices = tempDeviceList
})
},
},
mounted() {
this.getWifi()
this.paiList()
console.log(1)
}
})
</script>
<style lang="scss" scoped>
.device-list {
position: absolute;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
height: 80vh;
font-size: 0.24rem;
color: rgba(123, 124, 150, 1);
padding: 0.38rem 0.4rem 0.38rem;
background: rgba(255, 255, 255, 1);
border-radius: 0.4rem 0.4rem 0 0;
.feedback {
position: fixed;
right: 0.4rem;
bottom: 1rem;
padding: 0.2rem 0.2rem;
border: 1px solid;
border-radius: 0.16rem;
.cancle {
color: #ffffff;
}
}
p {
text-align: center;
margin: 0 0 0.38rem;
}
.content {
min-height: 80vh;
}
}
</style>
\ No newline at end of file
......@@ -10143,7 +10143,7 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.nlark.com/websocket-extensions/download/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha1-f4RzvIOd/YdgituV1+sHUhFXikI=
whatwg-fetch@>=0.10.0:
whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0:
version "3.6.2"
resolved "https://registry.nlark.com/whatwg-fetch/download/whatwg-fetch-3.6.2.tgz?cache=0&sync_timestamp=1624607940609&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwhatwg-fetch%2Fdownload%2Fwhatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
integrity sha1-3O0k838mJO0CgXJdUdDi4/5nf4w=
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment