vue端:
<template>
<div class="home">
<div class="home-header">
<el-row style="margin: 0">
<el-col :span="8" :offset="4">
<div class="home-header-search">
<p class="header-search-title">XXXXXXX</p>
<p class="header-search-subtitle">XXXXXXXXXX</p>
<el-input
class="header-search-input"
v-model="searchInput"
prefix-icon="el-icon-search"
placeholder="用户ID/存证HASH/TX哈希/区块高度/区块哈希"
/>
</div>
</el-col>
<el-col :span="8" class="home-header-image">
<img src="../assets/images/header/banner-image.png" />
</el-col>
</el-row>
</div>
<div class="home-main">
<div class="home-card">
<el-row :gutter="20">
<el-col :span="4" :offset="4">
<el-card shadow="always">
<p>区块数量</p>
<p class="info-card-content">{{ wsData["blocksCount"] }}</p>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="always">
<p>交易数量</p>
<p class="info-card-content">{{ wsData["transactionsCount"] }}</p>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="always">
<p>账户数量</p>
<p class="info-card-content">{{ wsData["accountsCount"] }}</p>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="always">
<p>存证数量</p>
<p class="info-card-content">{{ wsData["evidenceCount"] }}</p>
</el-card>
</el-col>
</el-row>
</div>
<el-row class="home-list">
<el-col :span="16" :offset="4" class="info-detail blcoks-list">
<div class="bs-callout bs-callout-primary">
<span class="bs-callout-title">区块</span>
<span class="bs-callout-sub-title">最新产生的区块</span>
<router-link to="/blocks" class="bs-callout-sub-more"
>查看更多</router-link
>
</div>
<tl-table :table="blockList"></tl-table>
</el-col>
<el-col :span="16" :offset="4" class="info-detail transactions-list">
<div class="bs-callout bs-callout-primary">
<span class="bs-callout-title">交易</span>
<span class="bs-callout-sub-title">最新产生的交易</span>
<router-link to="/transactions" class="bs-callout-sub-more"
>查看更多</router-link
>
</div>
<tl-table :table="transactionList" @onRowClick="rowClick"></tl-table>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import tlTable from "../components/recordlist.vue";
export default {
name: "home",
components: {
tlTable
},
data() {
return {
searchInput: "",
websock: null,
wsData: {
blocksCount: 0,
transactionsCount: 0,
accountsCount: 0,
evidenceCount: 0
},
infoData: {},
blockList: {
loading: true,
tr: [
{
id: "1",
label: "区块高度",
prop: "block_num",
// show: 'template',
width: "100",
className: "username"
},
{
id: "2",
label: "区块哈希",
prop: "block_id",
minWidth: 140
},
{
id: "3",
label: "TX数",
minWidth: "20",
prop: "block.transactions.length"
},
{
id: "4",
label: "出块时间",
prop: "createdAt"
},
{
id: "5",
label: "出块节点",
prop: "block.producer"
}
],
data: []
},
transactionList: {
loading: true,
tr: [
{
id: "1",
label: "交易序号",
prop: "block_num",
width: "100",
// show: 'template',
className: "username"
},
{
id: "2",
label: "交易hash",
prop: "id"
},
{
id: "4",
label: "出块时间",
prop: "createdAt"
}
],
data: []
}
};
},
methods: {
rowClick(row) {
this.$router.push({
path: "/transactions/transactionDetail/" + row["row"]["id"]
});
},
initWebSocket() {
// 初始化weosocket
const wsuri = "ws://111.111.111.111:0000/ws";
this.websock = new WebSocket(wsuri);
this.websock.onmessage = this.websocketonmessage;
this.websock.onopen = this.websocketonopen;
this.websock.onerror = this.websocketonerror;
this.websock.onclose = this.websocketclose;
s;
},
websocketonopen() {
// 连接建立之后执行send方法发送数据
let actions = { event: "home" };
this.websocketsend(JSON.stringify(actions));
},
websocketonerror() {
// 连接建立失败重连
this.initWebSocket();
},
websocketonmessage(data) {
// 数据接收
const wsData = JSON.parse(data.data);
if (wsData["event"] === "home") {
this.wsData = wsData.data;
}
},
websocketsend(Data) {
// 数据发送
this.websock.send(Data);
},
websocketclose(e) {
// 关闭
console.log("断开连接", e);
}
},
watch: {
wsData(val, oldVal) {
this.blockList.data = val["blockList"];
this.transactionList.data = val["transactionList"];
// this.infoData = val['info'];
},
"blockList.data": function(val) {
this.blockList.loading = false;
},
"transactionList.data": function(val) {
this.transactionList.loading = false;
}
},
beforeCreate() {
// 获取路由路径
sessionStorage.setItem("headerIndex", this.$route.path);
},
mounted() {
if (!this.websock) {
this.initWebSocket();
}
},
updated() {
// this.blockList.data = this.wsData['blockList'];
},
beforeDestroy() {
this.websock.close();
}
};
</script>
<style lang="less">
.header-search-input {
.el-input__inner {
border-radius: 20px;
}
}
</style>
<style scoped lang="less">
@import "../assets/css/wrapper";
.home {
.home-header {
min-height: 500px;
background: url("../assets/images/header/banner1.png") no-repeat;
background-size: cover;
.home-header-search {
color: #fff;
margin: 20% 0 100px 0;
.header-search-title {
font-size: 2.5em;
}
.header-search-subtitle {
font-size: 24px;
}
.header-search-input {
width: 80%;
}
}
.home-header-image {
/*padding-top: 120px;*/
img {
margin-top: 20%;
}
}
}
.home-main {
.home-card {
margin: 30px 10px;
font-weight: bold;
.info-card-content {
font-size: 20px;
color: rgb(64, 158, 255);
}
}
.home-list {
margin: 0;
.info-detail {
margin-top: 10px;
margin-bottom: 30px;
}
}
}
}
</style>
beego后端:
package routers
import (
"monitorServer/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/ws", &controllers.MyWebSocketController{})
}
package controllers
import (
"github.com/astaxie/beego"
"github.com/gorilla/websocket"
"log"
"monitorServer/models"
"time"
)
type MyWebSocketController struct {
beego.Controller
}
// 配置 upgrader
var upgrader = websocket.Upgrader{}
func (c *MyWebSocketController) Get() {
// 将初始GET请求升级到websocket
ws, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
if err != nil {
log.Fatal(err)
}
// 返回时关闭连接
defer ws.Close()
// 将新的客户端连接添加到字典中
clients[ws] = true
//不断的广播发送到页面上
for {
//目前存在问题 定时效果不好 需要在业务代码替换时改为beego toolbox中的定时器
time.Sleep(time.Second * 3)
msg := models.Message{Message: "这是向页面发送的数据 " + time.Now().Format("2006-01-02 15:04:05")}
broadcast <- msg
}
}
package controllers
import (
"monitorServer/models"
"log"
"github.com/gorilla/websocket"
)
// 使用字典结构更容易追加和删除内容
var (
clients = make(map[*websocket.Conn]bool) // 保存连接的客户端
broadcast = make(chan models.Message) // 消息广播通道
)
func init() {
go handleMessages()
}
// 发送
func handleMessages() {
for {
msg := <-broadcast
// 将其发送给当前连接的每个客户端
if len(clients) != 0 {
for client := range clients {
err := client.WriteJSON(msg)
if err != nil {
log.Printf("client.WriteJSON error: %v", err)
client.Close()
delete(clients, client)
}
}
}
}
}
package models
type Message struct {
Message string `json:"message"`
}
参考: