7 changed files with 750 additions and 165 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,148 @@ |
|||||
|
<template> |
||||
|
<custom-base-table |
||||
|
:data="data" |
||||
|
:columns="columns" |
||||
|
thead-classes="text-primary" |
||||
|
> |
||||
|
<template slot="LogType" slot-scope="item"> |
||||
|
{{ typeRender(item.row.item.LogType) }} |
||||
|
</template> |
||||
|
</custom-base-table> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import Bus from "../../common/bus"; |
||||
|
import CustomBaseTable from "../../components/CustomBaseTable"; |
||||
|
import moment from "moment"; |
||||
|
export default { |
||||
|
props: { |
||||
|
RobotId: { type: String, default: "60521323-28C3-AC14-0076-48B075584510" } |
||||
|
}, |
||||
|
components: { CustomBaseTable }, |
||||
|
data() { |
||||
|
return { |
||||
|
columns: [ |
||||
|
{ name: "RobotId", prop: "RobotId" }, |
||||
|
{ name: "内容", prop: "Content" }, |
||||
|
{ |
||||
|
name: "日志类型", |
||||
|
prop: "LogType", |
||||
|
|
||||
|
customSlot: "LogType" |
||||
|
}, |
||||
|
{ |
||||
|
name: "订单Id", |
||||
|
prop: "SpotGoodsOrderId" |
||||
|
}, |
||||
|
{ name: "创建时间", prop: "CreateTime" } |
||||
|
], |
||||
|
data: [], |
||||
|
noMoreData: false, |
||||
|
endTime: null, |
||||
|
scrollInstance: null, |
||||
|
nullPlusTime: 0 |
||||
|
}; |
||||
|
}, |
||||
|
created() { |
||||
|
let endTime = moment(); |
||||
|
this.endTime = endTime; |
||||
|
this.getLatestLog(endTime); |
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
Bus.$on("tradeLog", data => { |
||||
|
console.log(data, "received from ws Bus"); |
||||
|
this.data.unshift(data); |
||||
|
}); |
||||
|
this.initScroller(); |
||||
|
}, |
||||
|
|
||||
|
destroyed() { |
||||
|
if (this.scrollInstance) |
||||
|
this.scrollInstance.removeEventListener("scroll", this.scrollerListener); |
||||
|
}, |
||||
|
methods: { |
||||
|
initScroller() { |
||||
|
let target = document.getElementById("tradeLog"); |
||||
|
this.scrollInstance = target; |
||||
|
this.scrollInstance.addEventListener( |
||||
|
"scroll", |
||||
|
this.scrollerListener, |
||||
|
false |
||||
|
); |
||||
|
}, |
||||
|
|
||||
|
getPreday() {}, |
||||
|
|
||||
|
scrollerListener() { |
||||
|
// console.log( |
||||
|
// this.scrollInstance.scrollTop, |
||||
|
// this.scrollInstance.scrollHeight, |
||||
|
// this.scrollInstance.clientHeight |
||||
|
// ); |
||||
|
if ( |
||||
|
this.scrollInstance.scrollTop + this.scrollInstance.clientHeight == |
||||
|
this.scrollInstance.scrollHeight |
||||
|
) { |
||||
|
if (!this.spinning && !this.noMoreData) this.getLatestLog(this.endTime); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
typeRender(logType) { |
||||
|
switch (logType) { |
||||
|
case 0: |
||||
|
return "买入"; |
||||
|
case 1: |
||||
|
return "卖出"; |
||||
|
case 2: |
||||
|
return "做多"; |
||||
|
case 3: |
||||
|
return "做空"; |
||||
|
case 4: |
||||
|
return "大趋势看多"; |
||||
|
case 5: |
||||
|
return "大趋势看空"; |
||||
|
case 10: |
||||
|
return "自动卖出"; |
||||
|
} |
||||
|
}, |
||||
|
getLatestLog(endTime) { |
||||
|
this.spinning = true; |
||||
|
let _endTime = endTime.format("YYYY-MM-DD HH:mm:ss"); |
||||
|
|
||||
|
this.$http |
||||
|
.get( |
||||
|
`/Api/ExecutionLog/GetList?robotId=${this.RobotId}&endTime=${_endTime}` |
||||
|
) |
||||
|
.then(res => { |
||||
|
this.spinning = false; |
||||
|
if (res.Code == 200) { |
||||
|
if (res.Data.length > 0) { |
||||
|
if (this.data.length > 0) { |
||||
|
res.Data.forEach(item => this.data.push(item)); |
||||
|
this.endTime = moment( |
||||
|
this.data[this.data.length - 1].CreateTime |
||||
|
); |
||||
|
} else { |
||||
|
this.data = res.Data; |
||||
|
} |
||||
|
} else { |
||||
|
this.noMoreData = true; |
||||
|
this.sMessage("danger", "已经没有更多日志了"); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
// 封装showNotification |
||||
|
sMessage(type, message) { |
||||
|
this.$notify({ |
||||
|
type: type, |
||||
|
message, |
||||
|
timeout: 1800 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped></style> |
@ -0,0 +1,350 @@ |
|||||
|
<template> |
||||
|
<card> |
||||
|
<el-tabs v-model="activeName"> |
||||
|
<el-tab-pane label="历史订单" name="first"> |
||||
|
<custom-base-table |
||||
|
:data="historyOrders" |
||||
|
:columns="OrderColumns.filter(item => !item.hidden)" |
||||
|
thead-classes="text-primary" |
||||
|
></custom-base-table> |
||||
|
<el-pagination |
||||
|
small |
||||
|
:hide-on-single-page="true" |
||||
|
layout="prev, pager, next" |
||||
|
:total="historyOrdersPagination.total" |
||||
|
:page-size="historyOrdersPagination.pageSize" |
||||
|
:current-page="historyOrdersPagination.current" |
||||
|
> |
||||
|
</el-pagination> |
||||
|
</el-tab-pane> |
||||
|
<el-tab-pane label="持仓订单" name="second"> |
||||
|
<custom-base-table |
||||
|
:data="nowOrders" |
||||
|
:columns="OrderColumns" |
||||
|
thead-classes="text-primary" |
||||
|
></custom-base-table> |
||||
|
</el-tab-pane> |
||||
|
</el-tabs> |
||||
|
|
||||
|
<card> |
||||
|
<h5 slot="header" class="title">账号配置信息</h5> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input v-model="basic.CoinCount" label="持币数量" disabled> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input |
||||
|
v-model="basic.TotalPurchasePrice" |
||||
|
label="持仓总价" |
||||
|
disabled |
||||
|
> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input |
||||
|
v-model="basic.AvgPurchasePrice" |
||||
|
label="持仓均价" |
||||
|
disabled |
||||
|
> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input |
||||
|
v-model="basic.TotalPurchasePriceRatio" |
||||
|
label="持仓占比(%)" |
||||
|
disabled |
||||
|
> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input v-model="basic.FloatingPL" label="浮动盈亏(%)" disabled> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input |
||||
|
v-model="basic.TotalPurchasePriceProfit" |
||||
|
label="浮动持仓利润(已预扣手续费)" |
||||
|
disabled |
||||
|
> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input |
||||
|
v-model="basic.TotalProfit" |
||||
|
label="总利润(已预扣手续费)" |
||||
|
disabled |
||||
|
> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<base-input v-model="basic.NewestPrice" label="最新成交价" disabled> |
||||
|
</base-input> |
||||
|
</div> |
||||
|
</div> |
||||
|
</card> |
||||
|
</card> |
||||
|
</template> |
||||
|
<script> |
||||
|
import { OrderColumns } from "../../pages/prePages/js/columns"; |
||||
|
import CustomBaseTable from "../../components/CustomBaseTable"; |
||||
|
import Bus from "../../common/bus"; |
||||
|
|
||||
|
import { |
||||
|
sendSock, |
||||
|
initWebSocket, |
||||
|
closeWebSocket |
||||
|
} from "../../utils/plugin/socket"; |
||||
|
|
||||
|
const S_PING = 100; |
||||
|
const R_PONG = 101; |
||||
|
const SUBSCRIBE = 102; |
||||
|
const ACCOUNT_INFO = 103; |
||||
|
const ORDER_PUBLISH = 104; |
||||
|
const TRADE_LOG = 105; |
||||
|
|
||||
|
export default { |
||||
|
components: { CustomBaseTable }, |
||||
|
props: { |
||||
|
RobotId: { type: String, default: "60521323-28C3-AC14-0076-48B075584510" } |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
activeName: "first", |
||||
|
OrderColumns, |
||||
|
historyOrders: [], |
||||
|
nowOrders: [], |
||||
|
basic: {}, |
||||
|
historyOrdersPagination: { current: 1, pageSize: 15 }, |
||||
|
pingInterval: null |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
created() { |
||||
|
this.initOrders(); //初始化两个订单列表 |
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
console.log("connecting"); |
||||
|
this.initWs(); //初始化ws连接 |
||||
|
}, |
||||
|
|
||||
|
beforeDestroy() { |
||||
|
closeWebSocket(); |
||||
|
localStorage.clear(); |
||||
|
clearInterval(this.pingInterval); |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
initOrders() { |
||||
|
this.initHistoryOrders(); |
||||
|
this.initNowOrders(); |
||||
|
}, |
||||
|
initHistoryOrders() { |
||||
|
let pageIndex = this.historyOrdersPagination.current; |
||||
|
let pageSize = this.historyOrdersPagination.pageSize; |
||||
|
this.$http |
||||
|
.get( |
||||
|
`/Api/Order/GetHistorySpotGoodsOrder?pageIndex=${pageIndex}&pageSize=${pageSize}&robotId=${this.RobotId}` |
||||
|
) |
||||
|
.then(res => { |
||||
|
if (res.Code == 200) { |
||||
|
this.historyOrders = res.Data.List; |
||||
|
const pager = { ...this.historyOrdersPagination }; |
||||
|
pager.total = res.Data.Count; |
||||
|
this.historyOrdersPagination = pager; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
//触发分页 |
||||
|
historyOrdersChange(pagination) { |
||||
|
this.historyOrdersPagination = pagination; |
||||
|
this.initHistoryOrders(); |
||||
|
}, |
||||
|
|
||||
|
initNowOrders() { |
||||
|
this.$http |
||||
|
.get(`/Api/Order/GetRuningSpotGoodsOrder?robotId=${this.RobotId}`) |
||||
|
.then(res => { |
||||
|
if (res.Code == 200) { |
||||
|
this.nowOrders = res.Data; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
initWs() { |
||||
|
let that = this; |
||||
|
initWebSocket("ws://54.249.164.224").then( |
||||
|
rs => { |
||||
|
//订阅事件 |
||||
|
sendSock( |
||||
|
{ |
||||
|
Notify: SUBSCRIBE, |
||||
|
RobotId: this.RobotId |
||||
|
}, |
||||
|
that.wsCb |
||||
|
); |
||||
|
//ping包检测连接 |
||||
|
that.pingIntervalKeeper(); |
||||
|
}, |
||||
|
rj => { |
||||
|
that.$message.error("连接websocket失败,正在重连"); |
||||
|
that.initWs(); |
||||
|
} |
||||
|
); |
||||
|
}, |
||||
|
|
||||
|
wsCb(data) { |
||||
|
console.log("ws received", data); |
||||
|
|
||||
|
if (data && data.Notify == ACCOUNT_INFO) { |
||||
|
this.dealAccountInfo(data); |
||||
|
} else if (data && data.Notify == ORDER_PUBLISH) { |
||||
|
this.dealOrder(data); |
||||
|
} else if (data && data.Notify == R_PONG) { |
||||
|
this.dealPong(data); |
||||
|
} else if (data && data.Notify == TRADE_LOG) { |
||||
|
Bus.$emit("tradeLog", data); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
pingPkg() { |
||||
|
console.log("心跳包检测发送"); |
||||
|
let timeStamp = Date.now(); |
||||
|
let that = this; |
||||
|
sendSock( |
||||
|
{ |
||||
|
Notify: S_PING, |
||||
|
TimeStamp: timeStamp |
||||
|
}, |
||||
|
that.wsCb |
||||
|
); |
||||
|
localStorage.setItem("pingTimeStamp", timeStamp); |
||||
|
if (!localStorage.getItem("missPkg")) { |
||||
|
localStorage.setItem("missPkg", 1); |
||||
|
} else { |
||||
|
let missPkgCount = parseInt(localStorage.getItem("missPkg")) + 1; |
||||
|
localStorage.setItem("missPkg", missPkgCount); |
||||
|
console.log("丢包次数增加1", missPkgCount); |
||||
|
if (missPkgCount > 3) { |
||||
|
/** 达到丢包上限 |
||||
|
* 1.停止ping包interval |
||||
|
* 2.关闭ws |
||||
|
* 3.重新获取订单列表 |
||||
|
*/ |
||||
|
console.log("达到丢包次数", missPkgCount); |
||||
|
clearInterval(this.pingInterval); |
||||
|
localStorage.clear(); |
||||
|
closeWebSocket(); |
||||
|
this.initOrders(); |
||||
|
this.initWs(); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
//心跳包ping包定时发送 |
||||
|
pingIntervalKeeper() { |
||||
|
let that = this; |
||||
|
that.pingPkg(); |
||||
|
this.pingInterval = setInterval(() => { |
||||
|
that.pingPkg(); |
||||
|
}, 30000); |
||||
|
}, |
||||
|
|
||||
|
//心跳包pong包检测 |
||||
|
dealPong(data) { |
||||
|
//收到pong包后与本地得timeStamp匹配到之后丢包次数默认-1 |
||||
|
let timeStamp = localStorage.getItem("pingTimeStamp"); |
||||
|
let missPkgCount = parseInt(localStorage.getItem("missPkg")); |
||||
|
if (data.TimeStamp == timeStamp) { |
||||
|
missPkgCount--; |
||||
|
console.log("丢包次数减少1", missPkgCount); |
||||
|
localStorage.setItem("missPkg", missPkgCount); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
//账号信息推送处理 |
||||
|
dealAccountInfo(data) { |
||||
|
this.basic = { ...this.basic, ...data }; |
||||
|
if ( |
||||
|
this.nowOrders.length > 0 && |
||||
|
data.NewestPrice && |
||||
|
data.NewestPrice != 0 |
||||
|
) { |
||||
|
this.nowOrders.forEach(item => { |
||||
|
let totalSalePrice = data.NewestPrice * item.PurchaseCoinCount; //销售总价 |
||||
|
let saleFee = totalSalePrice * 0.02; //销售手续费 |
||||
|
let Profit = |
||||
|
totalSalePrice - |
||||
|
item.TotalPurchasePrice - |
||||
|
saleFee - |
||||
|
item.PurchaseFee; |
||||
|
item.Profit = Profit.toFixed(5); //算出利润 |
||||
|
item.UnstableProfit = ( |
||||
|
(data.NewestPrice / item.PurchasePrice - 1) * |
||||
|
100 |
||||
|
).toFixed(5); //算出浮动盈亏 |
||||
|
// console.log(item.UnstableProfit, "看看数据"); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
//订单推送处理 |
||||
|
dealOrder(data) { |
||||
|
//4|| 6 |
||||
|
let targetIndex = -1; |
||||
|
for (let i = 0; i < this.nowOrders.length; i++) { |
||||
|
if (data.Id == this.nowOrders[i].Id) { |
||||
|
targetIndex = i; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
if (targetIndex == -1) { |
||||
|
this.nowOrders.push(data); |
||||
|
} else { |
||||
|
this.nowOrders[targetIndex] = { |
||||
|
...this.nowOrders[targetIndex], |
||||
|
...data |
||||
|
}; |
||||
|
if (data.Status == 4 || data.Status == 6) { |
||||
|
this.nowOrders.splice(targetIndex, 1); |
||||
|
if (this.historyOrdersPagination.current == 1) |
||||
|
this.initHistoryOrders(); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
statusRender(status) { |
||||
|
//已创建=0,部分购买=1,已购买=2,部分购买被撤销=3,购买被撤销=4,部分卖出=5,已卖出=6,部分卖出已撤销=7,卖出已撤销=8 |
||||
|
switch (status) { |
||||
|
case 0: |
||||
|
return "已创建"; |
||||
|
case 1: |
||||
|
return "部分购买"; |
||||
|
case 2: |
||||
|
return "已购买"; |
||||
|
case 3: |
||||
|
return "部分购买被撤销"; |
||||
|
case 4: |
||||
|
return "购买被撤销"; |
||||
|
case 5: |
||||
|
return "部分卖出"; |
||||
|
case 6: |
||||
|
return "已卖出"; |
||||
|
case 7: |
||||
|
return "部分卖出已撤销"; |
||||
|
case 8: |
||||
|
return "卖出已撤销"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
<style> |
||||
|
.el-pagination button:disabled { |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
.el-pager li { |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue