You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

875 lines
28 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="tz-container">
<div class="tz-header">
<div>
<b-img class="tz-logo" src="/static/image/logo_white.png" />
<b-img src="/static/image/system_name.png" />
</div>
<div class="tz-flex">
<div @click="changeTab(0)" :class="tabId == 0 ?'tz-selected':''" >
<span> <b-img src="/static/image/system_icon1.png" /></span>
<span>首页</span>
</div>
<div @click="sim">
<span><b-img src="/static/image/system_icon2.png" /></span>
<span>仿真交易</span>
</div>
<div @click=" changeTab(2)" :class="tabId == 2 ?'tz-selected':''">
<span><b-img src="/static/image/system_icon3.png" /></span>
<span>排行榜</span>
</div>
<div @click="jixiao">
<span><b-img src="/static/image/system_icon4.png" /></span>
<span>绩效分析</span>
</div>
<div @click=" tabId = 4" :class="tabId == 4 ?'tz-selected':''">
<span><b-img src="/static/image/system_icon5.png" /></span>
<span>行为画像</span>
</div>
<div @click=" tabId = 6" :class="tabId == 6 ?'tz-selected':''">
<span><b-img src="/static/image/note.png" /></span>
<span>每日复盘</span>
</div>
<div @click=" tabId = 5" :class="tabId == 5 ?'tz-selected':''">
<span><b-img src="/static/image/system_icon6.png" /></span>
<span>行情中心</span>
</div>
</div>
</div>
<div v-if="tabId == 0">
<div class="comp-info">
<div class="comp-thumbnail">
<b-img fluid :src="!competition?'':competition.thumbnail" />
</div>
<div class="">
<div class="comp-info-title">
<span class="comp-type">{{ competition&&competition.type == 1?'团队赛':'个人赛' }}</span>
<span class="comp-title">{{ competition.name }}--{{ currentStage.name }}--证券投资赛项</span>
</div>
<hr />
<div class="comp-info-title">
<div class="comp-info-content">
<div>
<b-img src="/static/image/system_cmp_icon1.png"/>
<div>开始时间: {{ new Date(currentStage.startTime).Format('yyyy-MM-dd')}}</div>
</div>
<div>
<b-img src="/static/image/system_cmp_icon2.png"/>
<div>结束时间: {{ new Date(currentStage.endTime).Format('yyyy-MM-dd')}}</div>
</div>
<div>
<b-img src="/static/image/system_cmp_icon3.png"/>
<div>初始资金: {{ !taskInof?'':taskInof.initCapital}}元</div>
</div>
</div>
<div class="comp-info-content">
<div>
<b-img src="/static/image/system_cmp_icon4.png"/>
<div>交易品种: {{getTradeType() }}</div>
</div>
<div>
<b-img src="/static/image/system_cmp_icon5.png"/>
<div>参赛人数: {{competition.peopleCount}}人</div>
</div>
<div>
<b-img src="/static/image/system_cmp_icon6.png"/>
<div>行情类型: 实时</div>
</div>
</div>
</div>
</div>
</div>
<div class="tz-tab">
<b-container>
<b-img thumbnail @click="sim" src="/static/image/trade_sim.png" />
<b-img thumbnail @click=" changeTab(2)" src="/static/image/ranking_tab.png" />
<b-img thumbnail @click="jixiao" src="/static/image/jixiaofenxi.png" />
<b-img thumbnail @click=" tabId = 4" src="/static/image/xingweihuaxiang.png" />
</b-container>
</div>
<div class="tz-ranking">
<div class="tz-ranking-header">
<div>
<b-img src="/static/image/system_icon10.png" />
证券投资赛项个人排名趋势
</div>
<div>
创建日期{{new Date().Format("yyyy-MM-dd")}}
</div>
</div>
<div id="main" style="width:100%; height:100%">
</div>
</div>
</div>
<div v-if="tabId == 2">
<div class="comp-info">
<div class="tz-bold"> >>{{ !competition?'':competition.name }}--{{ !currentStage?'':currentStage.name }}--证券投资赛项 </div>
<div class="member-info">
<div>
<b-img src="/static/image/system_icon11.png"/>
<span> 欢迎</span>
<span>{{ userInfo.name}}</span>
</div>
<!-- <div>
<b-img src="/static/image/system_icon12.png" />
<span>退出</span>
</div> -->
</div>
</div>
<div class="tz-filter">
<div>
<span>日期</span>
<b-form-datepicker v-model="rankQuery.date" weekday-header-format="short" />
<span> 检索</span>
<b-input v-model="rankQuery.keyword" placeholder="用户名/所属院校/所属团队" />
<b-button class="tz-button" @click="rankSearch">查询</b-button>
<b-button class="tz-button">导出</b-button>
</div>
<!-- <div class="online-info">
<span>注册人数1090</span>
<span>在线人数: 687</span>
</div> -->
</div>
<div>
<div class="tz-table-header">
<div>
用户名
</div>
<div >
所属院校
</div>
<div>
所属团队
</div>
<div @click="rankSort('score')">
收益率折算分
<div class="tz-inline-block">
<div class="triangle_up"></div>
<div class="triangle_down"></div>
</div>
</div>
<div >
排名
</div>
<div>
期初资金
</div>
<div @click="rankSort('nav')">
总资产
<div class="tz-inline-block">
<div class="triangle_up"></div>
<div class="triangle_down"></div>
</div>
</div>
<div>
可用资金
</div>
<div>
市值
</div>
<div>
累计盈亏
</div>
<div>
浮动盈亏
</div>
<div>
<div>累计手续费</div>
</div>
<div @click="rankSort('totalRatio')">
<div>累计收益率</div>
<div class="tz-inline-block">
<div class="triangle_up"></div>
<div class="triangle_down"></div>
</div>
</div>
<div class="tz-flex-wrap">
<div>
基准收益率
</div>
<div>
(沪深300)
</div>
</div>
<div @click="rankSort('yearRatio')">
年化收益率
<div class="tz-inline-block">
<div class="triangle_up"></div>
<div class="triangle_down"></div>
</div>
</div>
<div v-if="isMobilePlatform == false">
最大回测
</div>
<div v-if="isMobilePlatform == false">
卡玛比率
</div>
<div v-if="isMobilePlatform == false">
夏普比率
</div>
<div v-if="isMobilePlatform == false">
开仓次数
</div>
<div v-if="isMobilePlatform == false">
平仓次数
</div>
<div v-if="isMobilePlatform == false">
胜率
</div>
</div>
<div class="tz-table-content">
<div class="tz-table-row" v-for="(item,$index) in list" :key="$index">
<div>{{ item.name}}</div>
<div style="text-align:left;">
<tz-tips v-if="item.school.length>maxWordLen" :content="item.school" :len="maxWordLen" />
<span v-if="item.school.length<=maxWordLen">{{item.school}}</span>
</div>
<div style="text-align:left;">
<tz-tips v-if="item.teamName.length>maxWordLen" :content="item.teamName" :len="maxWordLen"/>
<span v-if="item.teamName.length<=maxWordLen">{{item.teamName}} </span>
</div>
<div>{{ numberFixed(item.financeScore)}}</div>
<div>{{ item.personalRank}}</div>
<div>{{ item.initFounds}}</div>
<div>{{ numberFixed(item.nav)}}</div>
<div>{{ numberFixed(item.available)}}</div>
<div>{{ numberFixed(item.marketValue)}}</div>
<div>{{ numberFixed(item.profitLoss)}}</div>
<div>{{ numberFixed(item.fpnl)}}</div>
<div>{{ numberFixed(item.cumCommission)}}</div>
<div :class="item.pnlRatio>0?'tz-red':'tz-green'" >{{ numberFixed(item.pnlRatio*100)}}%</div>
<div :class="item.baseRatio>0?'tz-red':'tz-green'" >{{ numberFixed(item.baseRatio*100)}}%</div>
<div>{{ numberFixed(item.pnlRatioAnnual*100)}}%</div>
<div v-if="isMobilePlatform == false">{{ numberFixed(item.maxDrawdown*100)}}%</div>
<div v-if="isMobilePlatform == false">{{ numberFixed(item.calmarRatio)}}</div>
<div v-if="isMobilePlatform == false">{{ numberFixed(item.sharpRatio)}}</div>
<div v-if="isMobilePlatform == false">{{ item.openCount}}</div>
<div v-if="isMobilePlatform == false">{{ item.closeCount}}</div>
<div v-if="isMobilePlatform == false">{{ numberFixed(item.winRatio*100)}}%</div>
</div>
</div>
</div>
<div class="tz-pageable">
<span class="tz-page" @click="page(-1,1)">&lt;</span>
<div class="tz-page-number">
<span @click="page(1,2)" >首页</span>
<span v-for="index in getPrePage()" :key="index" @click="page(index,2)" class="current-page">{{index}}</span>
<span @click="page(totalPage,2)" >尾页</span>
</div>
<span class="tz-page" @click="page(1,1)">&gt;</span>
<span>到第</span>
<b-input style="width:5rem; margin:0; margin-right:.5rem" type="number" v-model="rankQuery.pageNo" @blur="loadRankinig2" />
<span>页</span>
<span>共{{rankQuery.total}}条/共{{this.totalPage}}页</span>
<!-- <b-select v-model="rankQuery.pageSize" @change="loadRankinig2">
<b-select-option value="20">20条/页</b-select-option>
<b-select-option value="30">30条/页</b-select-option>
<b-select-option value="50">50条/页</b-select-option>
</b-select> -->
</div>
</div>
<div v-if="tabId == 4">
<tz-portrait :competition="competition" :currentStage="currentStage" :memberInfo="memberInfo" :compId="compId" :stageId="stageId" />
</div>
<div v-if="tabId == 6">
<tz-note />
</div>
<div v-if="tabId == 5">
<tz-quotation />
</div>
<tz-footer />
</div>
</template>
<script>
import Footer from '@/components/footer'
import Quotation from './quotation.vue'
import Portrait from './portrait.vue'
import Note from './note.vue'
import * as echarts from 'echarts'
import { getInfo,loginout } from '@/utils/auth'
import * as competitionApi from '@/api/competition'
import * as memberApi from '@/api/member'
import * as rankingApi from '@/api/ranking'
import * as taskApi from '@/api/task'
import PaoMaDeng from '@/components/paomadeng2.vue'
import Tips from '@/components/tips.vue'
export default {
components:{
'tz-footer': Footer,
'tz-quotation': Quotation,
'tz-portrait': Portrait,
'tz-paomadeng': PaoMaDeng,
'tz-tips': Tips,
'tz-note': Note
},
methods:{
isMobile() {
let flag = !!navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
return flag;
},
sim(){
let endTime = new Date(this.currentStage.endTime).getTime()
console.log(this.currentStage)
if(endTime<new Date().getTime()){
alert("")
return
}
if(!this.memberInfo.accountPwd){
alert("");
return
}
let url = 'https://sim.sztzjy.com/user/login?token='+this.memberInfo.accountPwd+'&redirect=https://sim.sztzjy.com/sim?acc='+this.memberInfo.accountId
window.open(url,"onlywin",'toolbar=no, location=no,directoryies=no, status=no, menubar=no, scrollbars=yes, resizable=no, copyhistory=yes, height=600, width=1100, left=180, top=100')
},
jixiao(){
if(!this.memberInfo.accountPwd){
alert("");
return
}
if(!this.memberInfo.reportId){
alert("")
return
}else{
let url = 'https://sim.sztzjy.com/user/login?token='+this.memberInfo.accountPwd+'&redirect=https://sim.sztzjy.com/perfweb/analysis/profile/'+this.memberInfo.reportId
window.open(url,"onlywin",'toolbar=no, location=no,directoryies=no, status=no, menubar=no, scrollbars=yes, resizable=no, copyhistory=yes, height=600, width=1100, left=180, top=100')
}
},
getPrePage(){
let rs = []
for(var i = this.rankQuery.pageNo +1 ;i<this.rankQuery.pageNo+6;i++){
if(i<=this.totalPage){
rs.push(i)
}
}
return rs
},
page(step,type){
if(type ==1){
let pn = parseInt(this.rankQuery.pageNo)+parseInt(step);
if(pn>this.totalPage){
pn = this.totalPage
return
}
this.rankQuery.pageNo = pn
}else{
this.rankQuery.pageNo = parseInt(step)
}
if(this.rankQuery.pageNo<=0){
this.rankQuery.pageNo = 1
}else{
this.loadRankinig2()
}
},
getTradeType(){
console.log(this.taskInof)
if(this.taskInof.tradeType==1){
return "股票基金";
}else{
return "期货"
}
},
changeTab(id){
this.tabId = id
// console.log(this.tabId )
if(id==2){
this.loadRankinig2()
}
},
numberFixed(num){
if(typeof(num) == 'number'){
return num.toFixed(2)
}
return num
},
rankSearch(){
this.loadRankinig2()
},
loadData(){
memberApi.getMemberInfo(this.compId, this.stageId).then(res=>{
if(res.code == 200){
this.memberInfo = res.data
}else{
alert(res.msg)
if(res.msg == "token异常"){
loginout()
this.$router.push({
path: '/login'
})
}
}
})
},
loadRankinig2(){
this.rankQuery.compId = this.compId
this.rankQuery.stageId = this.stageId
rankingApi.list(this.rankQuery).then(res=>{
if(res.code == 200 ){
this.list = res.data.list
this.rankQuery.total = res.data.total
this.totalPage = Math.ceil(this.rankQuery.total/this.rankQuery.pageSize)
}
})
},
rankSort(key){
this.rankQuery.sort = key
if(this.rankQuery.direct == 0){
this.rankQuery.direct =1
}else{
this.rankQuery.direct = 0
}
this.loadRankinig2()
},
loadRankinig(){
rankingApi.listAll(this.compId,this.stageId).then(res=>{
if(res.code == 200){
this.drawRanking(res.data.list)
}
})
},
drawRanking(rankList){
let xData = []
let yData = []
rankList.forEach(item=>{
xData.push(item.updateTime)
yData.push(item.personalRank)
})
let option = {
tooltip: {
trigger: 'axis',
textStyle:{
align:'left'
},
},
xAxis: {
type: 'category',
data: xData,
axisLine: {
onZero: false
}
},
yAxis: {
type: 'value',
inverse: true
},
series: [
{
data: yData,
type: 'line',
color:['#7c89ff']
}
]
}
this.rankingCharts = echarts.init(document.getElementById('main'));
// if(!this.rankingCharts){
// }
// 绘制图表
this.rankingCharts.setOption(option,true);
// console.log("update ranking",this.rankingCharts)
}
},
data(){
return{
userInfo: null,
tabId: 0,
list:[
],
rankingCharts: null,
competition: null,
compId: 0 ,
stageId: 0,
currentStage: null,
memberInfo: null,
taskInof: null,
isMobilePlatform: false,
maxWordLen: 7,
rankQuery:{
pageNo: 1,
pageSize: 50,
date: '',
keyword: '',
sort: '',
direct: 0,
compId: 0,
stageId: 0
},
totalPage: 0
}
},
created(){
memberApi.updateInfo().then(res=>{})
this.isMobilePlatform = this.isMobile()
if(this.isMobilePlatform){
this.maxWordLen = 4
// this.rankQuery.pageSize=50;
}
this.userInfo = getInfo()
if(this.$route.query){
this.compId = this.$route.query.id
this.stageId = this.$route.query.stageId
this.loadData()
competitionApi.get({compId: this.compId}).then(res =>{
if(res.code == 200 ){
this.competition = res.data
let stage = this.competition.stageList.filter(s=>s.id == this.stageId)
if(stage.length>0){
this.currentStage = stage[0]
}
}
})
competitionApi.getGroup(this.compId,this.stageId).then(res=>{
// console.log("groupData:",res)
})
taskApi.get(this.compId,this.stageId).then(res=>{
if(res.code == 200){
this.taskInof =res.data
console.log("taskInof:",this.taskInof)
}
})
}
},
updated(){
if(this.tabId == 0 ){
this.$nextTick(()=>{
this.loadRankinig()
})
}
}
}
</script>
<style scoped>
.tz-green{
color: #00994f;
}
.tz-container{
padding-bottom: 3rem;
}
.tz-red{
color: #fe0000;
}
.tz-pageable{
background-color: #202a32;
display: flex;
color: white;
padding-top: .5rem;
padding-bottom: .5rem;
padding-left: .5rem;
font-size: 70%;
align-items: center;
}
.tz-page-number{
margin-right: .5rem;
display: flex;
justify-content: center;
align-items: center;
}
.tz-page-number>span{
margin-left: 0.1rem;
}
.tz-pageable>span{
margin-right: .5rem;
}
.current-page{
background-color: #0263d3;
padding: .3rem;
border-radius: 3px;
width: 2rem;
}
.tz-table-header{
display: flex;
color: white;
background-color: #666666;
justify-content: space-around;
font-weight: bold;
align-items: center;
font-size: 60%;
}
.tz-table-row{
display: flex;
justify-content: space-around;
align-items: center;
font-size: 50%;
border-bottom: 1px solid #dddddd;
}
.tz-table-row>div{
width: 100%;
border-left: 1px solid #cdcdcd;
padding-top: .4rem;
padding-bottom: .4rem;
}
.tz-table-row:nth-child(even){
background-color: #ededed;
}
/* .tz-table-row:nth-child(1){
background-color: #fecfb1;
color: #fe0000;
} */
.tz-table-row:nth-child(1)>div:nth-child(5){
background-color: #fd4b00;
color: white;
}
.tz-table-row:nth-child(2)>div:nth-child(5){
background-color: #656565;
color: white;
}
.tz-table-row:nth-child(3)>div:nth-child(5){
background-color: #b77a4d;
color: white;
}
.tz-table-row>div{
width: 100%;
}
.tz-tabel-bg-blue{
background-color: #0264d2 !important;
}
.tz-table-color-blue{
color: #5364db;
}
.tz-table-header>div{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid #797979;
border-bottom: 1px solid #797979;
border-right: 1px solid #797979;
height: 3rem;
}
.tz-flex-wrap{
flex-wrap: wrap;
}
.tz-inline-block{
display: inline-block;
}
.tz-header{
background-image: url('/static/image/answer_topbg_1990x140.jpg');
background-size: cover;
min-height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.tz-button{
background-color: #ff7800;
padding: 0 1rem 0 1rem;
margin-right: 1rem;
border-radius: 0;
border: none;
font-weight: bold;
}
.triangle_down{
width: 0;
height: 0;
border: 5px solid transparent;
border-top-color: white;
border-bottom: none;
border-left-color: transparent;
border-right-color: transparent;
}
.triangle_up{
width: 0;
height: 0;
border: 5px solid transparent;
border-bottom-color: white;
border-top: none;
border-left-color: transparent;
border-right-color: transparent;
margin-bottom: 2px;
}
.tz-logo{
width: 2rem;
margin-right: .5rem;
}
.online-info span{
margin-right: .5rem;
}
.tz-flex{
display: flex;
color: white;
margin-left: 10rem;
}
.tz-flex div{
min-height: 80px;
align-items: center;
display: flex;
flex-wrap: wrap;
padding: 1rem;
}
.tz-filter{
background-color: #202a32;
display: flex;
justify-content: space-between;
color: white;
padding-top: .5rem;
padding-bottom: .5rem;
}
.tz-filter>div{
display: flex;
align-items: center;
}
.online-info{
color: #f0f1f1;
font-size: 60%;
}
.form-control{
width: 11rem;
height: 1.5rem;
margin-left: 1rem;
margin-right: 1rem;
font-size: 60%;
border-radius: 0;
}
.tz-filter>div:nth-child(1){
width: 100%;
margin-left: 18rem;
}
.tz-filter>div:nth-child(2){
/* width: 15%; */
margin-right: 18rem;
}
.tz-flex div:hover{
background-color: #0264d2;
}
.tz-selected{
background-color: #0264d2 !important;
}
.tz-flex div span {
width: 100%;
display: block;
margin-bottom: .5rem;
}
.member-info{
width: 48%;
text-align: right;
display: flex;
justify-content: end;
}
.member-info div{
margin-right: 1rem;
vertical-align: middle;
}
.comp-info{
width: 100%;
background-color: #0264d2;
color: white;
display: flex;
justify-content: center;
align-items: center;
padding-top: .5rem;
padding-bottom: .5rem;
}
.comp-info-title{
display: flex;
flex-wrap: wrap;
align-items: center;
}
.comp-info-content{
display: flex;
width: 100%;
}
.comp-info-content>div{
width: 33%;
display: flex;
margin-top: 1rem;
}
.comp-info-content>div>img{
margin-right: .3rem;
}
.comp-thumbnail{
padding: 1rem;
}
.comp-thumbnail img {
border-radius: 3px;
border: 2px solid white;
margin-right: 1rem;
width: 18rem;
}
.comp-type{
display: inline-block;
background-color: #ff8400;
padding: .1rem 1rem .1rem 1rem;
margin-right: 1rem;
}
.comp-title{
font-weight: bolder;
font-size: 130%;
}
#main{
min-height: 387px;
max-width: 86rem;
background: white;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.tz-tab{
margin-top: 1rem;
display: flex;
justify-content: center;
}
.tz-tab div{
display: flex;
justify-content: space-between;
max-width: 86rem;
width: 100%;
}
.tz-tab img{
max-width: 25%;
}
.tz-ranking{
justify-content: center;
display: flex;
flex-wrap: wrap;
margin-bottom: 1rem;
}
.tz-ranking-header{
display: flex;
justify-content: center;
align-items: center;
max-width: 86rem;
width: 100%;
/* box-shadow: 10px 10px 5px #888888; */
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.tz-ranking-header div{
padding: 1rem;
}
.tz-ranking-header div:nth-child(1){
width: 80%;
text-align: left;
background-color: #0263d3;
color: white;
border-top-left-radius: 10px;
font-weight: bold;
font-size: 100%;
}
.tz-ranking-header div:nth-child(2){
width: 20%;
text-align: right;
background-color: #2b2b2b;
color: white;
border-top-right-radius: 10px;
}
</style>