完善部分信息的显示
This commit is contained in:
parent
2facd8f67a
commit
975969a1b9
121
assets/css/main.css
Normal file
121
assets/css/main.css
Normal file
@ -0,0 +1,121 @@
|
||||
.small-address {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.loader {
|
||||
background: #00000035;
|
||||
background: radial-gradient(#22222282, #00000059);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.loader-inner {
|
||||
bottom: 0;
|
||||
height: 60px;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100px;
|
||||
}
|
||||
.loader-tip {
|
||||
bottom: 0;
|
||||
height: 60px;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.loader-tip .msg {
|
||||
color: white;
|
||||
line-height: 216px;
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
.loader-line-wrap {
|
||||
animation: spin 2000ms cubic-bezier(0.175, 0.885, 0.32, 1.275) infinite;
|
||||
box-sizing: border-box;
|
||||
height: 50px;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transform-origin: 50% 100%;
|
||||
width: 100px;
|
||||
}
|
||||
.loader-line {
|
||||
border: 4px solid transparent;
|
||||
border-radius: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 100px;
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100px;
|
||||
}
|
||||
.loader-line-wrap:nth-child(1) {
|
||||
animation-delay: -50ms;
|
||||
}
|
||||
.loader-line-wrap:nth-child(2) {
|
||||
animation-delay: -100ms;
|
||||
}
|
||||
.loader-line-wrap:nth-child(3) {
|
||||
animation-delay: -150ms;
|
||||
}
|
||||
.loader-line-wrap:nth-child(4) {
|
||||
animation-delay: -200ms;
|
||||
}
|
||||
.loader-line-wrap:nth-child(5) {
|
||||
animation-delay: -250ms;
|
||||
}
|
||||
|
||||
.loader-line-wrap:nth-child(1) .loader-line {
|
||||
border-color: hsl(0, 80%, 60%);
|
||||
height: 90px;
|
||||
width: 90px;
|
||||
top: 7px;
|
||||
}
|
||||
.loader-line-wrap:nth-child(2) .loader-line {
|
||||
border-color: hsl(60, 80%, 60%);
|
||||
height: 76px;
|
||||
width: 76px;
|
||||
top: 14px;
|
||||
}
|
||||
.loader-line-wrap:nth-child(3) .loader-line {
|
||||
border-color: hsl(120, 80%, 60%);
|
||||
height: 62px;
|
||||
width: 62px;
|
||||
top: 21px;
|
||||
}
|
||||
.loader-line-wrap:nth-child(4) .loader-line {
|
||||
border-color: hsl(180, 80%, 60%);
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
top: 28px;
|
||||
}
|
||||
.loader-line-wrap:nth-child(5) .loader-line {
|
||||
border-color: hsl(240, 80%, 60%);
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
top: 35px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0%,
|
||||
15% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
@ -11,17 +11,7 @@ const DEFAULT_CHAIN_DATA = {
|
||||
symbol: "MATIC",
|
||||
explorerurl: "https://mumbai.polygonscan.com/",
|
||||
};
|
||||
const loader = document.getElementById("loader");
|
||||
// 显示加载动画
|
||||
function showLoading() {
|
||||
// add style display: block
|
||||
loader.style.display = "block";
|
||||
}
|
||||
// 隐藏加载动画
|
||||
function hideLoading() {
|
||||
// add style display: none
|
||||
loader.style.display = "none";
|
||||
}
|
||||
|
||||
async function loadJson(url) {
|
||||
return fetch(url).then((response) => response.json());
|
||||
}
|
||||
@ -83,25 +73,62 @@ createApp({
|
||||
contract: null,
|
||||
wallet: null,
|
||||
disabled: false,
|
||||
loading: false,
|
||||
loadingMask: false,
|
||||
showCancel: false,
|
||||
showConfirm: false,
|
||||
loadingTxt: "加载中",
|
||||
chainId: 0,
|
||||
hasPermission: false, // 当前用户是否有权限执行confirm
|
||||
alertShow: false,
|
||||
alertMsg: "",
|
||||
alertType: "success",
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
let params = getAllParameter();
|
||||
this.id = params.id;
|
||||
console.log("taskid: ", this.id);
|
||||
let result = await fetchTaskInfo(this.id);
|
||||
this.task = result.chainTask;
|
||||
this.subTasks = result.requestTasks;
|
||||
this.address = result.address;
|
||||
this.types = result.types;
|
||||
console.log(result);
|
||||
await this.initWallet();
|
||||
this.loading = true;
|
||||
try {
|
||||
let params = getAllParameter();
|
||||
this.id = params.id;
|
||||
console.log("taskid: ", this.id);
|
||||
let result = await fetchTaskInfo(this.id);
|
||||
this.task = result.chainTask;
|
||||
this.subTasks = result.requestTasks;
|
||||
this.address = result.address;
|
||||
this.types = result.types;
|
||||
console.log(result);
|
||||
await this.initWallet();
|
||||
} catch (err) {
|
||||
this.alert("加载数据失败", "danger", true);
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
methods: {
|
||||
alert(msg, type, autoClose = false) {
|
||||
this.alertMsg = msg;
|
||||
this.alertType = type;
|
||||
this.alertShow = true;
|
||||
if (autoClose) {
|
||||
setTimeout(() => {
|
||||
this.closeAlert();
|
||||
}, 3000);
|
||||
}
|
||||
},
|
||||
closeAlert() {
|
||||
this.alertShow = false;
|
||||
},
|
||||
showType(type) {
|
||||
return this.types[type];
|
||||
},
|
||||
// 显示加载动画
|
||||
showLoadingMask(txt) {
|
||||
this.loadingTxt = txt || "加载中";
|
||||
this.loadingMask = true;
|
||||
},
|
||||
// 隐藏加载动画
|
||||
hideLoadingMask() {
|
||||
this.loadingMask = false;
|
||||
},
|
||||
async initInstance(user, address, jsonUrl) {
|
||||
let json = await loadJson(jsonUrl);
|
||||
return new this.web3.eth.Contract(json.abi, address, { from: user });
|
||||
@ -121,46 +148,116 @@ createApp({
|
||||
this.chainId = await this.web3.eth.getChainId();
|
||||
this.walletConnect = true;
|
||||
console.log(this.chainId, this.account);
|
||||
console.log(this.contract);
|
||||
await this.refreshData();
|
||||
},
|
||||
async refreshData() {
|
||||
let hasRole = await this.checkRole();
|
||||
console.log("has role: ", hasRole);
|
||||
let cando = true;
|
||||
let canCancel = false;
|
||||
for (let sub of this.subTasks) {
|
||||
let status = await this.querySchedule(sub.scheduleId);
|
||||
console.log("task status: ", status);
|
||||
sub.taskExists = status[0]; // 任务是否在链上存在
|
||||
sub.executed = status[1]; // 是否已经执行了
|
||||
sub.confirmed = status[2]; // 是否已经满足多签条件
|
||||
sub.selfConfirm = status[3]; // 当前用户是否已经确认
|
||||
let statusArr = [];
|
||||
if (!sub.taskExists) {
|
||||
cando = false;
|
||||
statusArr.push(["任务未上链", "danger"]);
|
||||
}
|
||||
if (sub.selfConfirm) {
|
||||
cando = false;
|
||||
statusArr.push(["已确认", "danger"]);
|
||||
}
|
||||
if (sub.confirmed) {
|
||||
cando = false;
|
||||
statusArr.push(["已满足条件", "danger"]);
|
||||
}
|
||||
if (sub.executed) {
|
||||
cando = false;
|
||||
statusArr.push(["已执行", "danger"]);
|
||||
}
|
||||
if (sub.selfConfirm && !sub.executed) {
|
||||
canCancel = true;
|
||||
}
|
||||
if (statusArr.length === 0 && cando) {
|
||||
statusArr.push(["可操作", "info"]);
|
||||
}
|
||||
|
||||
sub.statusArr = statusArr;
|
||||
}
|
||||
this.showCancel = canCancel;
|
||||
this.showConfirm = cando;
|
||||
},
|
||||
async checkRole() {
|
||||
let roleConfirm = await this.contract.methods.CONFIRM_ROLE().call();
|
||||
let result = await this.contract.methods
|
||||
.hasRole(roleConfirm, this.account)
|
||||
.call();
|
||||
return result;
|
||||
},
|
||||
makeBatchRequest(calls, callFrom) {
|
||||
let batch = new this.web3.BatchRequest();
|
||||
let promises = calls.map((call) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = call.request({ from: callFrom }, (error, data) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
batch.add(request);
|
||||
});
|
||||
});
|
||||
batch.execute();
|
||||
return Promise.all(promises);
|
||||
},
|
||||
async confirmTask() {
|
||||
let ids = this.subTasks.map((o) => o.scheduleId);
|
||||
console.log("confirm task", ids);
|
||||
showLoading();
|
||||
this.showLoadingMask("处理上链请求");
|
||||
try {
|
||||
let gas = await this.contract.methods
|
||||
.confirmTransaction(ids)
|
||||
.estimateGas();
|
||||
gas = gas | 0;
|
||||
await this.contract.methods.confirmTransaction(ids).send({ gas });
|
||||
await this.refreshData();
|
||||
} catch (err) {
|
||||
console.log("error confirm task", err);
|
||||
}
|
||||
hideLoading();
|
||||
this.hideLoadingMask();
|
||||
},
|
||||
async rejectTask() {
|
||||
console.log("reject task");
|
||||
let ids = this.subTasks.map((o) => o.scheduleId);
|
||||
showLoading();
|
||||
this.showLoadingMask("撤销确认信息");
|
||||
try {
|
||||
let gas = await this.contract.methods
|
||||
.revokeConfirmation(ids)
|
||||
.estimateGas();
|
||||
gas = gas | 0;
|
||||
await this.contract.methods.revokeConfirmation(ids).send({ gas });
|
||||
await this.refreshData();
|
||||
} catch (err) {
|
||||
console.log("error confirm task", err);
|
||||
}
|
||||
hideLoading();
|
||||
this.hideLoadingMask();
|
||||
},
|
||||
|
||||
async querySchedule(id) {
|
||||
let instance = wallet.contract;
|
||||
return makeBatchRequest([
|
||||
instance.methods.isOperation(id).call,
|
||||
instance.methods.isOperationPending(id).call,
|
||||
instance.methods.isOperationReady(id).call,
|
||||
instance.methods.isOperationDone(id).call,
|
||||
instance.methods.isConfirmed(id).call,
|
||||
let instance = this.contract;
|
||||
return this.makeBatchRequest([
|
||||
instance.methods.isOperation(id).call, //id是否在合约里
|
||||
// instance.methods.isOperationPending(id).call, // 任务是否在等待执行
|
||||
// instance.methods.isOperationReady(id).call, // 任务是否已经准备好, 但未执行
|
||||
instance.methods.isOperationDone(id).call, // 任务是否已经执行
|
||||
instance.methods.isConfirmed(id).call, // 任务是否已经已经满足多签的条件
|
||||
instance.methods.confirmations(id, this.account).call, //当前用户是否已经确认
|
||||
instance.methods.required().call, //多签的最小确认数
|
||||
instance.methods.getTimestamp(id).call,
|
||||
]);
|
||||
},
|
||||
|
@ -1,12 +1,12 @@
|
||||
(function() {
|
||||
var params = getAllParameter()
|
||||
console.log(params)
|
||||
console.log(location)
|
||||
var next = `confirm.html?id=${params.id}`
|
||||
if (isMobile()) {
|
||||
var url = `https://metamask.app.link/dapp/${location.host}/ct/${next}`
|
||||
document.getElementById('href').setAttribute('href', url)
|
||||
} else {
|
||||
// location.href = url
|
||||
}
|
||||
})()
|
||||
(function () {
|
||||
var params = getAllParameter();
|
||||
console.log(params);
|
||||
console.log(location);
|
||||
var next = `confirm.html?id=${params.id}`;
|
||||
if (isMobile()) {
|
||||
var url = `https://metamask.app.link/dapp/xwork.kingsome.cn/pages/${next}`;
|
||||
document.getElementById("href").setAttribute("href", url);
|
||||
} else {
|
||||
location.href = url;
|
||||
}
|
||||
})();
|
||||
|
67
confirm.html
67
confirm.html
@ -24,15 +24,15 @@
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
|
||||
<style>
|
||||
.small-address{
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="assets/css/main.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" class="container">
|
||||
<div class="alert alert-dismissible fixed-top" :class="'alert-'+alertType" role="alert" v-if="alertShow">
|
||||
<div>{{alertMsg}}</div>
|
||||
<button type="button" class="btn-close" @click="closeAlert" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
{{task.name}} - <small>{{task.starterName}}</small>
|
||||
@ -45,28 +45,35 @@
|
||||
<button type="button" class="btn btn-info" @click="initWallet">连接钱包</button>
|
||||
<div class="vr"></div>
|
||||
</template>
|
||||
<button type="button" class="btn btn-primary" :disabled="disabled" @click="confirmTask">确认</button>
|
||||
<button type="button" class="btn btn-primary" v-if="showConfirm" @click="confirmTask">确认</button>
|
||||
<div class="vr"></div>
|
||||
<button type="button" class="btn btn-danger" :disabled="disabled">拒绝</button>
|
||||
<button type="button" class="btn btn-danger" v-if="showCancel" @click="rejectTask">取消</button>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item" v-for="(item, i) in subTasks" >
|
||||
<h2 class="accordion-header" id="heading{{i}}">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{i}}" aria-expanded="true" aria-controls="collapse{{i}}">
|
||||
任务{{item.index}}: {{item.reqDatas.length}}个子任务
|
||||
<h2 class="accordion-header" :id="'heading'+i">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" :data-bs-target="'#collapse'+i" aria-expanded="true" :aria-controls="'collapse'+i">
|
||||
任务数{{item.index}}: {{item.reqDatas.length}}
|
||||
<div class="spinner-border" role="status" v-if="loading">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<template v-for="sub in item.statusArr">
|
||||
<span class="badge" :class="'text-bg-'+sub[1]">{{sub[0]}}</span>
|
||||
</template>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse{{i}}" class="accordion-collapse collapse show" aria-labelledby="heading{{i}}" data-bs-parent="#accordionExample">
|
||||
<div :id="'collapse'+i" class="accordion-collapse collapse show" :aria-labelledby="'heading'+i" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<div v-for="sub in item.reqDatas" class="border-bottom">
|
||||
<p><label class="text-secondary">类型:</label> {{showType(sub.type)}}</p>
|
||||
<p class="small-address"><label class="text-secondary">合约地址: </label>{{sub.address}}</p>
|
||||
<p class="small-address" v-if="sub.from"><label class="text-secondary">转出钱包: </label>{{sub.from}}</p>
|
||||
<p class="small-address"><label class="text-secondary">目标钱包: </label>{{sub.to}}</p>
|
||||
<p v-if="sub.amount"><label class="text-secondary">数量: </label>{{sub.amount}}</p>
|
||||
<p v-if="sub.tokenId"><label class="text-secondary">NFT ID: </label>{{sub.tokenId}}</p>
|
||||
<p v-if="sub.tokenid || sub.tokenId"><label class="text-secondary">NFT ID: </label>{{sub.tokenId || sub.tokenid}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -74,26 +81,30 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="loader" id="loader">
|
||||
<div class="loader-inner">
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
<div class="loader" id="loader" v-if="loadingMask">
|
||||
<div class="loader-inner">
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
</div>
|
||||
<div class="loader-line-wrap">
|
||||
<div class="loader-line"></div>
|
||||
<div class="loader-tip">
|
||||
<div class="msg">{{loadingTxt}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vconsole@3.15.0/dist/vconsole.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/web3@1.9.0/dist/web3.min.js"></script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user