市场行情 页面修改

This commit is contained in:
simple321vip
2023-01-04 14:23:30 +08:00
parent abdf29afaa
commit 92c084765d
7 changed files with 165 additions and 112 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ const routes: Array<RouteRecordRaw> = [
path: '/strategy',
component: () => import('../view/trader/cta_strategy_file.vue'),
meta: {
name: '策略文件'
name: '策略模板'
}
},
{
+5
View File
@@ -0,0 +1,5 @@
const toPercent = (num: number) => {
return (num * 100).toFixed(2) + "%"
}
export { toPercent }
+1 -1
View File
@@ -531,7 +531,7 @@ const onUploadImg = async (files: FileList, callback: (urls: string[]) => void)
return new Promise((resolve, reject) => {
const formData = new FormData()
formData.append('img', file)
onUploadImg(formData,)
// onUploadImg(formData,)
})
})
)
+35 -33
View File
@@ -34,8 +34,8 @@
<h3 style="cursor: pointer; width: min-content;white-space:nowrap" @click="openBlog(item.bid)">{{ item.title }}</h3>
<div style="display: flex; justify-content: space-between; align-items: center">
<p style="font-size: 12px; height: 16px;line-height: 16px;overflow: hidden;text-overflow: ellipsis;">{{
item.content
}}</p>
item.content
}}</p>
<el-button size="small" type="success" @click="publishbyBid(item.bid)">重新发布
</el-button>
</div>
@@ -52,20 +52,22 @@ import Cookies from 'js-cookie';
import { reactive } from 'vue';
import { getBlogs, getBtName, publish, publishAll } from '../../api/blogView'
import router from '../../router/index'
type Blog = {
bid: string,
btId: string,
btName: string,
title: string,
blog_prex: string,
// -- INTERFACE OR TYPE DEFINITION --
interface Blog {
bid: string
btId: string
btName: string
title: string
blog_prex: string
content: string
}
type Blog_Type = {
btId: string,
interface Blog_Type {
btId: string
btName: string
}
// 変数定義
// -- REACTIVE OBJECT --
const form = reactive({
key_word: '',
btId: '',
@@ -78,26 +80,7 @@ const form = reactive({
const data_list = reactive<Blog[]>([])
const btNameList = reactive<Blog_Type[]>([])
// 関数定義
const init = () => {
getBlogs({}).then(response => {
response.data.forEach((item: Blog) => {
data_list.push(item)
})
})
getBtName().then(response => {
btNameList.push({ btId: "", btName: "选择分类" })
response.data.forEach((item: any) => {
const bts = {
btId: item.btId,
btName: item.btName
}
btNameList.push(bts)
})
})
}
// -- EVENT DEFINITION
const onSubmit = () => {
getBlogs(form).then(response => {
data_list.splice(0, data_list.length);
@@ -134,9 +117,28 @@ const publishbyBid = (bid: string) => {
publish(bid)
}
// 初期化処理
init()
/**
* AUTO INVOKE FUNCTION
*/
(() => {
getBlogs({}).then(response => {
response.data.forEach((item: Blog) => {
data_list.push(item)
})
})
getBtName().then(response => {
btNameList.push({ btId: "", btName: "选择分类" })
response.data.forEach((item: any) => {
const bts = {
btId: item.btId,
btName: item.btName
}
btNameList.push(bts)
})
})
})()
</script>
<style>
+56 -33
View File
@@ -11,7 +11,7 @@
</div>
</el-col>
<el-col :span="3">
<el-tag size="small"> {{account_data.account_id}}</el-tag>
<el-tag size="small"> {{ account_data.account_id }}</el-tag>
</el-col>
<el-col :span="1">
<div class="cell-item">
@@ -21,7 +21,7 @@
</div>
</el-col>
<el-col :span="3">
<el-tag size="small"> {{account_data.balance}}</el-tag>
<el-tag size="small"> {{ account_data.balance }}</el-tag>
</el-col>
<el-col :span="1">
<div class="cell-item">
@@ -31,7 +31,7 @@
</div>
</el-col>
<el-col :span="3">
<el-tag size="small"> {{account_data.frozen}}</el-tag>
<el-tag size="small"> {{ account_data.frozen }}</el-tag>
</el-col>
<el-col :span="1">
<div class="cell-item">
@@ -41,32 +41,34 @@
</div>
</el-col>
<el-col :span="3">
<el-tag size="small"> {{account_data.gateway_name}}</el-tag>
<el-tag size="small"> {{ account_data.gateway_name }}</el-tag>
</el-col>
</el-row>
</el-collapse-item>
<el-collapse-item title="手动下单" name="2" style="display: flex;">
<el-collapse-item title="手动下单" name="2">
<el-select v-model="vt_symbol" placeholder="select a vt_symbol" @change="select_contract">
<el-option v-for="symbol in store.subscribe_vt_symbols" :value="symbol" />
</el-select>
<div style="height: 10px;"></div>
<el-row>
<el-col :span="2">
<el-col :span="5">
<el-radio-group v-model="direction">
<el-radio-button label="多" />
<el-radio-button label="空" />
</el-radio-group>
</el-col>
<el-col :span="2">
<el-col :span="4">
<el-radio-group v-model="offset">
<el-radio-button label="开" />
<el-radio-button label="平" />
</el-radio-group>
</el-col>
<el-col :span="1"></el-col>
<el-col :span="3">
<el-select v-model="vt_symbol" placeholder="select a vt_symbol" @change="select_contract">
<el-option v-for="symbol in store.subscribe_vt_symbols" :value="symbol" />
</el-select>
</el-col>
<el-col :span="1"></el-col>
<el-col :span="4">
</el-row>
<div style="height: 10px;"></div>
<el-row>
<el-col :span="5">
<el-input-number v-model="volume" :min="1" :max="10" @change="handleChange" />
</el-col>
<el-col :span="4">
@@ -75,7 +77,9 @@
<el-col :span="4">
<el-button type="primary" @click="on_order">下单</el-button>
</el-col>
<el-col :span="7"></el-col>
</el-row>
</el-collapse-item>
<el-collapse-item title="持仓一览" name="3">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
@@ -134,14 +138,19 @@
import { ElMessage, TabsPaneContext } from 'element-plus'
import { reactive, ref, h, onMounted, onUnmounted } from 'vue'
import { get_accounts, send_order, get_tick } from '../../api/capital'
import { strategyStore } from '../../store/strategy';
type AccountData = {
import { strategyStore } from '../../store/strategy'
// -- IMPORT --
const store = strategyStore()
// -- INTERFACE OR TYPE DEFINITION --
interface AccountData {
gateway_name: string
account_id: string
balance: number
frozen: number
}
type PositionData = {
interface PositionData {
symbol: string
exchange: string
direction: string
@@ -151,7 +160,7 @@ type PositionData = {
pnl: number
yd_volume: number
}
type OrderData = {
interface OrderData {
symbol: string
exchange: string
direction: string
@@ -165,7 +174,7 @@ type OrderData = {
// datetime :datetime
reference: string
}
type TradeData = {
interface TradeData {
symbol: string
exchange: string
direction: string
@@ -176,7 +185,14 @@ type TradeData = {
offset: string
// datetime: datetime
}
const store = strategyStore()
// -- REACTIVE OBJECT --
const account_datas = reactive<AccountData[]>([])
const positions_data = reactive<PositionData[]>([])
const trades_data = reactive<TradeData[]>([])
const orders_data = reactive<OrderData[]>([])
// -- REF OBJECT --
const vt_symbol = ref<string>("")
const direction = ref('多')
const offset = ref('开')
@@ -184,12 +200,9 @@ const activeName = ref(1)
const volume = ref(1)
const price = ref(3000)
const timer = ref(0)
const account_datas = reactive<AccountData[]>([])
const positions_data = reactive<PositionData[]>([])
const trades_data = reactive<TradeData[]>([])
const orders_data = reactive<OrderData[]>([])
const activeNames = ref(['1'])
// -- EVENT DEFINITION
const on_query_accounts = () => {
get_accounts().then(res => {
account_datas.length = 0
@@ -212,14 +225,15 @@ const on_query_accounts = () => {
})
})
return on_query_accounts
}
const select_contract = () => {
get_tick(vt_symbol.value).then(res => {
price.value = res.data.tick.last_price
})
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
@@ -227,6 +241,7 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
const handleChange = (value: number) => {
console.log(value)
}
const on_order = () => {
""
@@ -251,13 +266,21 @@ const on_order = () => {
})
}
onMounted(() => {
clearInterval(timer.value)
timer.value = window.setInterval(on_query_accounts, 3000);
})
onUnmounted(() => {
window.clearInterval(timer.value);
})
/**
* AUTO INVOKE FUNCTION
*/
(() => {
store.select_subscribe_vt_symbols()
onMounted(() => {
clearInterval(timer.value)
timer.value = window.setInterval(on_query_accounts(), 3000);
})
onUnmounted(() => {
window.clearInterval(timer.value);
})
})()
</script>
+42 -28
View File
@@ -30,13 +30,15 @@
<el-table @row-contextmenu="rightClickRow" @cell-mouse-enter="rowMouseEnter" @cell-mouse-leave="rowMouseLeave"
:data="ticks_data" style="width: 100%">
<el-table-column fixed prop="symbol" label="symbol" width="80" />
<el-table-column fixed prop="exchange" label="exchange" width="100" />
<el-table-column fixed prop="name" label="Name" width="120" />
<el-table-column fixed prop="last_price" label="last_price" width="120" />
<el-table-column fixed prop="volume" label="volume" width="100" />
<el-table-column fixed prop="open_price" label="open_price" width="120" />
<el-table-column fixed prop="high_price" label="high_price" width="120" />
<el-table-column fixed prop="low_price" label="low_price" width="120" />
<el-table-column prop="exchange" label="exchange" width="100" />
<el-table-column prop="name" label="Name" width="120" />
<el-table-column prop="last_price" label="last_price" width="120" />
<el-table-column prop="volume" label="volume" width="100" />
<el-table-column prop="open_price" label="open_price" width="120" />
<el-table-column prop="high_price" label="high_price" width="120" />
<el-table-column prop="low_price" label="low_price" width="100" />
<el-table-column prop="differ" label="differ" width="70" />
<el-table-column prop="differ_percent" label="differ_per" :formatter="Formatter" width="120" />
</el-table>
</el-collapse-item>
</el-collapse>
@@ -56,7 +58,8 @@ import { ref, h, onMounted, onUnmounted, reactive, getCurrentInstance } from 'vu
import { ElMessage } from 'element-plus'
import { get_ticks, subscribe, concel_subscribe } from '../../api/capital'
import { strategyStore } from '../../store/strategy'
import { Contextmenu, ContextmenuItem } from "v-contextmenu";
import { Contextmenu, ContextmenuItem } from "v-contextmenu"
import { toPercent } from '../../utils/number'
import * as echarts from 'echarts'
// -- IMPORT --
@@ -73,6 +76,8 @@ interface TickData {
open_price: number
high_price: number
low_price: number
differ: number
differ_percent: number
}
@@ -99,6 +104,8 @@ const on_subscribe = () => {
h('i', { style: 'color: green' }, "行情订阅成功"),
]),
})
store.select_subscribe_vt_symbols()
on_ticks()
}).catch(error => {
ElMessage({
message: h('p', null, [
@@ -108,6 +115,31 @@ const on_subscribe = () => {
})
}
const concelSubscribe = () => {
if (!selection.value) {
return
}
concel_subscribe(selection.value).then(res => {
ElMessage({
message: h('p', null, [
h('i', { style: 'color: green' }, "取消订阅成功"),
]),
})
on_ticks()
}).catch(error => {
ElMessage({
message: h('p', null, [
h('i', { style: 'color: red' }, "取消订阅失败"),
]),
})
})
}
const Formatter = (row, column) => {
let diff = (row.last_price - row.open_price) / row.open_price
return toPercent(diff)
}
const rowMouseEnter = (row: any, column: any, cell: any, event: any) => {
selection.value = row.symbol + "." + row.exchange
console.log(selection.value)
@@ -141,25 +173,7 @@ const on_ticks = () => {
ticks_data.push(element)
});
})
}
const concelSubscribe = () => {
if (!selection.value) {
return
}
concel_subscribe(selection.value).then(res => {
ElMessage({
message: h('p', null, [
h('i', { style: 'color: green' }, "取消订阅成功"),
]),
})
}).catch(error => {
ElMessage({
message: h('p', null, [
h('i', { style: 'color: red' }, "取消订阅失败"),
]),
})
})
return on_ticks
}
/**
@@ -169,7 +183,7 @@ const concelSubscribe = () => {
onMounted(() => {
clearInterval(timer.value)
timer.value = window.setInterval(on_ticks, 3000);
timer.value = window.setInterval(on_ticks(), 3000);
})
onUnmounted(() => {
window.clearInterval(timer.value)
+25 -16
View File
@@ -3,11 +3,11 @@
<el-upload ref="upload" class="upload-demo" action="http://localhost:5000/trader/api/v1/strategy_file" :limit="1"
:on-exceed="handleExceed" :auto-upload="false">
<template #trigger>
<el-button type="primary">添加策略文件</el-button>
<el-button type="primary">添加策略模板</el-button>
</template>
->
<el-button class="ml-3" type="success" @click="on_upload">
上传策略文件
上传策略模板
</el-button>
<template #tip>
<div class="el-upload__tip text-red">
@@ -78,23 +78,20 @@ import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
import { h } from 'vue'
import { ElMessage } from 'element-plus'
const upload = ref<UploadInstance>()
const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
upload.value!.handleStart(file)
}
type StrategyFile = {
file_name: string,
class_name: string,
// -- INTERFACE OR TYPE DEFINITION --
interface StrategyFile {
file_name: string
class_name: string
status: string
}
// -- REACTIVE OBJECT --
const strategy_file_list = reactive<StrategyFile[]>([])
// -- REF OBJECT --
const upload = ref<UploadInstance>()
// -- EVENT DEFINITION
const on_list = () => {
get_strategy_files().then(res => {
strategy_file_list.length = 0
@@ -104,6 +101,13 @@ const on_list = () => {
})
}
const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
upload.value!.handleStart(file)
}
const on_upload = () => {
upload.value!.submit()
@@ -145,10 +149,15 @@ const on_remove = (row: any) => {
})
}
// init process
on_list()
/**
* AUTO INVOKE FUNCTION
*/
(() => {
on_list()
})()
</script>
<style scoped>