Browse Source

新增股票页面

master
liaoxinyu 3 weeks ago
parent
commit
468eb7e791
  1. 8
      api/exchange.js
  2. 15
      api/market.js
  3. 16
      api/order.js
  4. 2
      app.js
  5. 12
      i18n/lang/en.json
  6. 12
      i18n/lang/zh-TW.json
  7. 6
      pages.json
  8. 11
      pages/base/index.vue
  9. 242
      pages/base/stockexchange-operation.vue
  10. 96
      pages/stockexchange/coin-info.vue
  11. 90
      pages/stockexchange/current-commission.vue
  12. 202
      pages/stockexchange/depth-map.vue
  13. 1133
      pages/stockexchange/exchange-transaction.vue
  14. 177
      pages/stockexchange/exchangeHis.vue
  15. 60
      pages/stockexchange/history-commisson.vue
  16. 566
      pages/stockexchange/index.vue
  17. 46
      pages/stockexchange/latest-transaction.vue
  18. 92
      pages/stockexchange/sale.vue
  19. 132
      pages/stockexchange/sell-and-buy.vue
  20. 177
      pages/stockexchange/symbol-list.vue
  21. 339
      pages/stockexchange/time-sharing.vue

8
api/exchange.js

@ -6,6 +6,10 @@ class Exchange {
static getUserBalance(data) { static getUserBalance(data) {
return Serve.get(`/exchange/getUserCoinBalance`,data); return Serve.get(`/exchange/getUserCoinBalance`,data);
} }
static getstockUserBalance(data) {
return Serve.get(`/stock/getUserCoinBalance`,data);
}
/** /**
* 提交订单 * 提交订单
@ -22,6 +26,10 @@ class Exchange {
static storeEntrust(data,config) { static storeEntrust(data,config) {
return Serve.post(`/exchange/storeEntrust`, data,config); return Serve.post(`/exchange/storeEntrust`, data,config);
} }
static stockstoreEntrust(data,config) {
return Serve.post(`/stock/storeEntrust`, data,config);
}
// 获取币种基本信息 // 获取币种基本信息
static getSymbolInfo(data) { static getSymbolInfo(data) {

15
api/market.js

@ -50,6 +50,21 @@ class Market {
static getCoinInfo(data){ static getCoinInfo(data){
return Serve.get(`/exchange/getCoinInfo`,data) return Serve.get(`/exchange/getCoinInfo`,data)
} }
// 初始化查询市场行情
static getstockMarketList() {
return Serve.get(`/stock/getMarketList`);
}
// 初始化买卖盘数据
static getstockBooks(data) {
return Serve.get(`/stock/getMarketInfo`,data);
}
// 获取币种信息
static getstockCoinInfo(data){
return Serve.get(`/stock/getCoinInfo`,data)
}
} }

16
api/order.js

@ -24,6 +24,9 @@ class Order {
static getHistoryEntrust(data) { static getHistoryEntrust(data) {
return Serve.get(`/exchange/getHistoryEntrust`,data); return Serve.get(`/exchange/getHistoryEntrust`,data);
} }
static getstockHistoryEntrust(data) {
return Serve.get(`/stock/getHistoryEntrust`,data);
}
/** /**
* 获取当前委托 * 获取当前委托
* @param {object} data * @param {object} data
@ -35,11 +38,20 @@ class Order {
static getCurrentEntrust(data) { static getCurrentEntrust(data) {
return Serve.get(`/exchange/getCurrentEntrust`,data); return Serve.get(`/exchange/getCurrentEntrust`,data);
} }
static getstockCurrentEntrust(data) {
return Serve.get(`/stock/getCurrentEntrust`,data);
}
// 获取止盈止损单 // 获取止盈止损单
static getConditionEntrust(data) { static getConditionEntrust(data) {
return Serve.get(`/exchange/getConditionEntrust`,data); return Serve.get(`/exchange/getConditionEntrust`,data);
} }
//当前委托
static stockholdPosition(data) {
return Serve.get(`/stock/holdPosition`,data);
}
/** /**
* 获取委托成交记录 * 获取委托成交记录
@ -64,6 +76,10 @@ class Order {
static cancelEntrust(data) { static cancelEntrust(data) {
return Serve.post(`/exchange/cancelEntrust`,data); return Serve.post(`/exchange/cancelEntrust`,data);
} }
static stockcancelEntrust(data) {
return Serve.post(`/stock/cancelEntrust`,data);
}
/** /**
* 批量撤单 * 批量撤单
* @param {object} data * @param {object} data

2
app.js

@ -9,7 +9,7 @@ if (process.env.NODE_ENV == 'production'||true) { //生产环境
// socket地址 // socket地址
socketUrl: 'wss://adm.moabwalletss.com/ws1', socketUrl: 'wss://adm.moabwalletss.com/ws1',
socketUrl1: 'wss://adm.moabwalletss.com/ws2', socketUrl1: 'wss://adm.moabwalletss.com/ws2',
socketUrl3: 'wss://adm.moabwalletss.com/ws3', socketUrl2: 'wss://adm.moabwalletss.com/ws3',
// pc端地址 // pc端地址
pcUrl:'https://www.moabwalletss.com/', pcUrl:'https://www.moabwalletss.com/',
// app名称 // app名称

12
i18n/lang/en.json

@ -362,7 +362,17 @@
"g3": "Operation", "g3": "Operation",
"g4": "Cancel", "g4": "Cancel",
"g5": "Whether to cancel the current order", "g5": "Whether to cancel the current order",
"g6": "Undo successfully" "g6": "Undo successfully",
"g7": "Stock",
"g8": "Current Holdings",
"g9": "Code/Name",
"g10": "Market Value of Holdings",
"g11": "Quantity",
"g12": "Latest Price",
"g13": "Cost",
"g14": "Today's Profit/Loss",
"g15": "Position Profit/Loss",
"g16": "Position Profit/Loss Ratio"
}, },
"option": { "option": {
"a0": "Options", "a0": "Options",

12
i18n/lang/zh-TW.json

@ -362,7 +362,17 @@
"g3": "操作", "g3": "操作",
"g4": "撤銷", "g4": "撤銷",
"g5": "是否撤銷當前委託", "g5": "是否撤銷當前委託",
"g6": "撤銷成功" "g6": "撤銷成功",
"g7": "股票",
"g8": "当前持倉",
"g9": "代碼/名稱",
"g10": "持倉市值",
"g11": "數量",
"g12": "最新價",
"g13": "成本",
"g14": "今日盈虧",
"g15": "持倉盈虧",
"g16": "持倉盈虧比例"
}, },
"option": { "option": {
"a0": "期權", "a0": "期權",

6
pages.json

@ -176,6 +176,12 @@
{ {
"path" : "pages/oncs/onservice" "path" : "pages/oncs/onservice"
}, },
{
"path": "pages/stockexchange/index"
},
{
"path": "pages/stockexchange/exchangeHis"
},
{ {
"path": "pages/service/index", "path": "pages/service/index",
"style": { "style": {

11
pages/base/index.vue

@ -53,6 +53,8 @@ import OptionList from "./option-list";
// import List from "./list"; // import List from "./list";
import Contract from "./contract"; import Contract from "./contract";
import StockexchangeOperation from "./stockexchange-operation";
export default { export default {
name: "Base", name: "Base",
components: { components: {
@ -62,7 +64,8 @@ export default {
Mine, Mine,
Contract, Contract,
Purchase, Purchase,
Help Help,
StockexchangeOperation
}, },
computed: { computed: {
navList() { navList() {
@ -85,6 +88,12 @@ export default {
icon: "static/img/index/base_caidan_0.png", icon: "static/img/index/base_caidan_0.png",
activeIcon: "static/img/index/base_caidan_1.png", activeIcon: "static/img/index/base_caidan_1.png",
}, },
{
label: this.$t("exchange.g7"),
tel: "stockexchange-operation",
icon: "static/img/base_qukuai_0.png",
activeIcon: "static/img/base_qukuai_1.png",
},
// { // {
// // label: this.$t("base.a4"), // // label: this.$t("base.a4"),
// // tel: "option-list", // // tel: "option-list",

242
pages/base/stockexchange-operation.vue

@ -0,0 +1,242 @@
<template>
<view class="d-flex flex-col">
<view style="height: var(--status-bar-height)"></view>
<!-- <view class="d-flex justify-center p-t-md">
<view class="d-flex bg-form-panel-4 rounded-lg overflow-scroll">
<view
:class="{ 'bg-gradient-blue color-plain rounded-lg': tab == 0 }"
@click="tab = 0"
class="p-y-xs p-x-lg min-w-60 fn-center"
>{{$t('exchange.a0')}}</view
>
<view
:class="{ 'bg-gradient-blue color-plain rounded-lg': tab == 1 }"
@click="tab = 1"
class="p-y-xs p-x-lg min-w-60 fn-center"
>{{$t('exchange.a1')}}</view
>
</view>
</view> -->
<!-- 币币 -->
<template v-if="tab == 0">
<!-- 币币交易 -->
<view
class="coin-exchange-box flex-fill d-flex flex-col overflow-hidden border-b"
>
<!-- <van-tabs
:ellipsis="false"
:border="false"
:active="tab1"
@change="tab1 = $event.detail.name"
>
<van-tab class="height-max" :title="$t('exchange.a3')"></van-tab>
<van-tab class="height-max" :title="$t('exchange.a4')"></van-tab>
<van-tab class="height-max" :title="$t('exchange.a5')"></van-tab>
</van-tabs> -->
<!-- 交易表单 -->
<exchange-transaction
@symbol="symbolListShow = true"
:marketList="marketList"
:collect="collect"
:query="query"
@option="option"
:isShow="isShow"
:tabs="tabs"
:increase="increase"
class="layout-main"
v-if="tab1 == 0 && query.symbol"
/>
<!-- 当前委托 -->
<current-commission class="layout-main" v-if="tab1 == 1" />
<!-- 历史委托 -->
<history-commisson class="layout-main" v-if="tab1 == 2" />
</view>
</template>
<!-- 申购 -->
<template v-if="tab == 1">
<purchase />
</template>
<!-- 左侧的弹窗 -->
<van-popup
:show="symbolListShow"
@close="symbolListShow = false"
close-on-popstate
position="left"
custom-style="height:100%;width:70%"
>
<symbol-list
:collect="collect"
:marketList="marketList"
:heyue="0"
@check-symbol="checkSymbol"
:symbols="symbols"
/>
</van-popup>
<van-toast id="van-toast" />
</view>
</template>
<script>
import exchangeTransaction from "@/pages/stockexchange/exchange-transaction";
import currentCommission from "@/pages/stockexchange/current-commission";
import historyCommisson from "@/pages/stockexchange/history-commisson";
import symbolList from "@/pages/stockexchange/symbol-list";
import purchase from "@/pages/purchase/index";
import Market from "@/api/market";
import Home from "@/api/home";
import { mapState } from "vuex";
export default {
name: "stockexchange-operation",
props: {
isShow: {
default: false,
type: Boolean,
required: false,
},
tabs: {
default: '',
type: String,
required: false,
},
},
components: {
exchangeTransaction,
currentCommission,
historyCommisson,
symbolList,
purchase,
},
data() {
return {
tab: 0,
tab1: 0,
symbolListShow: false,
marketList: [],
collect: [],
query: {},
msg: "exchangeMarketList",
increase:{},
symbols:''
};
},
watch: {
isShow(n) {
if (n) {
setTimeout(() => {
this.ws.send({
cmd: "sub",
msg: this.msg,
});
}, 200);
} else {
this.ws.send({
cmd: "unsub",
msg: this.msg,
});
}
},
},
computed: {
...mapState({
ws: "ws",
}),
isLogin() {
return Boolean(uni.getStorageSync("token"));
},
},
methods: {
//
getMarketList() {
Market.getstockMarketList().then((res) => {
this.marketList = res.data;
this.$nextTick(() => {
this.linkSocket();
});
if (!this.query.symbol) {
let parentItem = this.marketList[0].marketInfoList[0];
this.checkSymbol(parentItem);
}
});
},
//
getCollect() {
if (!this.isLogin) return;
Home.getCollect()
.then((res) => {
this.collect = res.data || [];
})
.catch(() => {});
},
//
checkSymbol(obj) {
this.symbols=obj.coin_name
this.symbolListShow = false;
if (obj.pair_name == this.query.symbol) return;
this.query = { symbol: obj.pair_name };
// this._router.replace({ query: { symbol: obj.pair_name } });
},
//
option() {
let data = {
pair_name: this.query.symbol,
};
Home.option(data)
.then((res) => {
this.getCollect();
if (res.data) {
this.$toast(this.$t("exchange.a6"));
} else {
this.$toast(this.$t("exchange.a7"));
}
})
.catch(() => {});
},
// socket
linkSocket() {
let msg = this.msg;
this.ws.send({
cmd: "sub",
msg,
});
this.ws.on("message", (res) => {
let { data, sub } = res;
if (sub == msg) {
this.marketList = data;
var symbol=this.query.symbol.split('/')
// console.log(symbol)
var market=this.marketList.find((item) => item.coin_name == symbol[1])
this.increase=market.marketInfoList.find((item) => item.coin_name == symbol[0])||{}
}
});
},
//
getQuery() {
let curPage = getCurPage();
let curParam = curPage.options || curPage.$route.query;
function getCurPage() {
let pages = getCurrentPages();
let curPage = pages[pages.length - 1];
return curPage;
}
return curParam;
},
},
created() {
this.query = this.getQuery();
if (this.query.symbol) {
this.query.symbol = decodeURIComponent(this.query.symbol);
}
this.getMarketList();
this.getCollect();
},
destroyed() {
this.ws.send({
cmd: "unsub",
msg: 'exchangeMarketList',
})
},
};
</script>
<style lang="scss" scoped>
</style>

96
pages/stockexchange/coin-info.vue

@ -0,0 +1,96 @@
<template>
<div>
<div class="coin p-md color-light fn-20">
<img :src="detail.coin_icon" width="20" height="20" alt="">
{{detail.full_name}}
</div>
<div class="list">
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('exchange.a8')}}</div>
<div class="color-light">
{{detail.total_issuance}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('exchange.a9')}}</div>
<div class="color-light">
{{detail.total_circulation}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('exchange.b0')}}</div>
<div class="color-light">
{{detail.crowdfunding_price}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('exchange.b1')}}</div>
<div class="color-light">
{{detail.publish_time}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div class="flex-shrink">{{$t('exchange.b2')}}</div>
<div class="color-light d-flex">
<div class="address eps-1 p-r-xs m-r-xs border-r fn-wrap">
{{detail.white_paper_link}}
</div>
<div class="color-sell flex-shrink" @click="$copy(detail.white_paper_link)">{{$t('common.copy')}}</div>
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div class="flex-shrink">{{$t('exchange.b3')}}</div>
<div class="color-light d-flex">
<div class="address eps-1 p-r-xs m-r-xs border-r fn-wrap">
{{detail.official_website_link}}
</div>
<div class="color-sell flex-shrink" @click="$copy(detail.official_website_link)">{{$t('common.copy')}}</div>
</div>
</div>
</div>
<div class="p-md">
<div class="fn-20 color-light">
{{$t('exchange.b4')}}
</div>
<div class="p-y-md edit-content" v-html="detail.coin_content">
</div>
</div>
</div>
</template>
<script>
import Market from '@/api/market'
export default {
props:{
query:{
default:{}
}
},
data(){
return {
detail:{}
}
},
watch:{
['query.code'](){
this.getCoinInfo()
}
},
methods:{
getCoinInfo(){
let data = {
coin_name:this.query.code.split('/')[0],
lang:uni.getStorageSync('language')=='zh-CN'?'zh-CN':'en'
}
Market.getstockCoinInfo(data).then(res=>{
this.detail = res.data
})
}
},
created(){
this.getCoinInfo()
}
}
</script>
<style lang="scss" scoped>
</style>

90
pages/stockexchange/current-commission.vue

@ -0,0 +1,90 @@
<template>
<v-paging :ajax="getCurrentEntrust" ref="list" tag="div">
<template #box="list">
<not-data v-if="!$list(list).length"></not-data>
<div v-for="item in $list(list)" class="item bg-panel-4 m-md rounded-sm box-shadow" :key="item.order_no">
<div class="head d-flex align-center border-b p-x-md p-y-xs justify-between">
<div class="d-flex">
<div v-if="item.entrust_type==1" class="suatus color-buy fn-20 m-r-xs rounded">{{$t('exchange.b5')}}</div>
<div v-if="item.entrust_type==2" class="suatus color-sell fn-20 m-r-xs rounded">{{$t('exchange.b6')}}</div>
<div>
<div class="color-light fn-20">{{item.symbol}}</div>
<div class="fn-10">{{item.created_at}}</div>
</div>
</div>
<div class="d-flex">
<span>{{item.status_text}}</span>
</div>
</div>
<div class="p-x-md p-y-xs">
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b7')}}</div>
<div class="color-light">{{item.entrust_price}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b8')}}</div>
<div class="color-light">
<template v-if="item.type==1">{{$t('exchange.b9')}}</template>
<template v-if="item.type==2">{{$t('exchange.c0')}}</template>
</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c1')}}</div>
<div class="color-buy">{{item.traded_amount}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c2')}}</div>
<div class="color-light">{{item.amount}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.g3')}}</div>
<div class="color-light">
<v-button type="red" class="rounded-xs" size="mini" @click="ifCancel(item)">{{$t('exchange.g4')}}</v-button>
</div>
</div>
</div>
</div>
</template>
</v-paging>
</template>
<script>
import Order from "@/api/order";
export default {
data() {
return {
getCurrentEntrust: Order.getstockCurrentEntrust,
};
},
methods: {
ifCancel(item) {
this.$dialog
.confirm({
title: this.$t('common.tips'),
message: this.$t('exchange.g5')+'?',
confirmButtonText: this.$t("common.confirm"),
cancelButtonText: this.$t("common.cancel")
})
.then(() => {
this.cancelEntrust(item);
})
.catch(() => {});
},
//
cancelEntrust(item) {
let data = {
entrust_id: item.id,
entrust_type: item.entrust_type,
symbol: item.symbol,
};
Order.stockcancelEntrust(data).then(() => {
this.$toast.success(this.$t('exchange.g6'));
this.$refs.list.list.forEach((ele, idx) => {
if (item.id == ele.id) {
this.$refs.list.list.splice(idx, 1);
}
});
});
},
},
};
</script>

202
pages/stockexchange/depth-map.vue

@ -0,0 +1,202 @@
<template>
<div
:prop="config"
:change:prop="depthmap.changeConfig"
class="depthMap bg-panel-1"
ref="depthMap"
></div>
</template>
<script>
export default {
props: {
serveSellList: {
default() {
return [];
},
type: Array,
},
serveBuyList: {
default() {
return [];
},
type: Array,
},
},
data() {
return {
config:{}
};
},
computed: {
mapConfig() {
return {
chart: {
type: "areaspline",
spacingRight: 0,
spacingLeft: 0,
zoomType: "xy",
backgroundColor: "transparent",
},
title: { text: null },
credits: {
enabled: false,
},
tooltip: {
// enabled: false,
},
xAxis: {
visible: false,
},
yAxis: {
visible: false,
},
legend: {
floating: true,
verticalAlign: "top",
// rtl: true,
},
plotOptions: {
area: {
fillOpacity: 0.2,
lineWidth: 1,
step: "center",
},
},
series: [
{
name: this.$t("exchange.b5"),
lineWidth: 1,
data: [],
marker: {
enabled: false,
},
color: "#00c162",
fillColor: {
linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 },
stops: [
[0, "rgba(2,150,82,.5)"],
[1, "rgba(2,150,82,.2)"],
],
},
},
{
name: this.$t("exchange.b6"),
lineWidth: 1,
data: [],
marker: {
enabled: false,
},
color: "#dd1900",
fillColor: {
linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 },
stops: [
[0, "rgba(221,25,0,.5)"],
[1, "rgba(221,25,0,.2)"],
],
},
// fillColor:'#00c162'
},
],
};
},
},
watch: {
serveSellList() {
this.resetData();
},
serveBuyList() {
this.resetData();
},
},
methods: {
getConfig(){
return {
type:'initPage',
sellList:this.serveSellList,
buyList:this.serveBuyList,
config:this.mapConfig
}
},
resetData(){
this.config = {
type:'resetData',
sellList:this.serveSellList,
buyList:this.serveBuyList,
}
}
},
created() {
this.config = this.getConfig()
},
};
</script>
<script module="depthmap" lang="renderjs">
import Highcharts from "highcharts/highstock";
export default {
data(){
return {
buyList:[],
sellList:[],
chartConfig:{},
chart: undefined,
}
},
methods: {
initMap() {
this.chart = Highcharts.chart(this.$refs.depthMap, this.chartConfig);
},
getBuyList() {
let arr = this.buyList
.map((item) => {
return [item.price*1, item.amount];
})
.sort((a, b) => a[0] - b[0]);
return arr;
},
getSellList() {
let arr = this.sellList
.map((item) => {
return [item.price*1, item.amount];
})
.sort((a, b) => a[0] - b[0]);
return arr;
},
setData(){
this.chart.series[0].setData(this.getBuyList());
this.chart.series[1].setData(this.getSellList());
},
changeConfig(n){
this.task(n)
},
task(obj){
switch (obj.type) {
case 'initPage':
this.buyList = obj.buyList
this.sellList = obj.sellList
this.chartConfig = obj.config
break;
case 'resetData':
this.buyList = obj.buyList;
this.sellList = obj.sellList
this.setData()
break;
default:
break;
}
}
},
mounted() {
this.task(this.config)
this.initMap();
},
}
</script>
<style lang="scss" scoped>
.depthMap {
height: 200px;
}
</style>

1133
pages/stockexchange/exchange-transaction.vue

File diff suppressed because it is too large

177
pages/stockexchange/exchangeHis.vue

@ -0,0 +1,177 @@
<template>
<v-page class="layout-main">
<v-header :title="$t('first.a6')"></v-header>
<view class="d-flex border-b">
<view class="d-flex rounded-lg justify-between w-max p-b-xs">
<view
@click="active = 0"
class="p-y-xs p-x-lg fn-center w-50"
>
<text :class="{ 'color-theme-1 active p-b-xs': active == 0 }">{{$t('first.a7')}}</text>
</view>
<view
@click="active = 1"
class="p-y-xs p-x-lg fn-center w-50"
>
<text :class="{ 'color-theme-1 active p-b-xs': active == 1 }">{{$t('first.a8')}}</text>
</view
>
</view>
</view>
<v-paging :ajax="getCurrentEntrust" :key="1" ref="list" tag="div" v-if="active==0">
<template #box="list">
<not-data v-if="!$list(list).length"></not-data>
<div v-for="item in $list(list)" class="item bg-panel-4 m-md rounded-sm box-shadow" :key="item.order_no">
<div class="head d-flex align-center border-b p-x-md p-y-xs justify-between">
<div class="d-flex">
<div v-if="item.entrust_type==1" class="suatus color-buy fn-20 m-r-xs rounded">{{$t('exchange.b5')}}</div>
<div v-if="item.entrust_type==2" class="suatus color-sell fn-20 m-r-xs rounded">{{$t('exchange.b6')}}</div>
<div>
<div class="color-light fn-20">{{item.symbol}}</div>
<div class="fn-10">{{item.created_at}}</div>
</div>
</div>
<div class="d-flex">
<span>{{item.status_text}}</span>
</div>
</div>
<div class="p-x-md p-y-xs">
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b7')}}</div>
<div class="color-light">{{item.entrust_price}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b8')}}</div>
<div class="color-light">
<template v-if="item.type==1">{{$t('exchange.b9')}}</template>
<template v-if="item.type==2">{{$t('exchange.c0')}}</template>
</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c1')}}</div>
<div class="color-buy">{{item.traded_amount}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c2')}}</div>
<div class="color-light">{{item.amount}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.g3')}}</div>
<div class="color-light">
<v-button type="red" class="rounded-xs" size="mini" @click="ifCancel(item)">{{$t('exchange.g4')}}</v-button>
</div>
</div>
</div>
</div>
</template>
</v-paging>
<v-paging class="layout-main" :key="2" :ajax="getHistoryEntrust" v-if="active==1">
<template #box="list">
<not-data v-if="!$list(list).length"></not-data>
<div v-for="item in $list(list)" class="item bg-panel-4 m-md rounded-sm box-shadow" :key="item.order_no">
<div class="head d-flex align-center border-b p-x-md p-y-xs justify-between">
<div class="d-flex">
<div v-if="item.entrust_type==1" class="suatus color-buy fn-20 m-r-xs rounded">{{$t('exchange.b5')}}</div>
<div v-if="item.entrust_type==2" class="suatus color-sell fn-20 m-r-xs rounded">{{$t('exchange.b6')}}</div>
<div>
<div class="color-light fn-20">{{item.symbol}}</div>
<div class="fn-10">{{item.created_at}}</div>
</div>
</div>
<div>{{item.status_text}}</div>
</div>
<div class="p-x-md p-y-xs">
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b7')}}</div>
<div class="color-light">{{item.entrust_price}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b8')}}</div>
<div class="color-light">
<template v-if="item.type==1">{{$t('exchange.b9')}}</template>
<template v-if="item.type==2">{{$t('exchange.c0')}}</template>
</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c1')}}</div>
<div class="color-buy">{{item.traded_amount}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.e2')}}</div>
<div class="color-light">{{item.avg_price}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c2')}}</div>
<div class="color-light">{{item.amount}}</div>
</div>
</div>
</div>
</template>
</v-paging>
</v-page>
</template>
<script>
import Order from "@/api/order";
import math from '@/utils/class/math'
export default {
data(){
return {
active: 0,
getHistoryEntrust: Order.getstockHistoryEntrust,
getCurrentEntrust: Order.getstockCurrentEntrust,
}
},
methods:{
division:math.division,
ifCancel(item) {
this.$dialog
.confirm({
title: this.$t('common.tips'),
message: this.$t('exchange.g5')+'?',
confirmButtonText: this.$t("common.confirm"),
cancelButtonText: this.$t("common.cancel")
})
.then(() => {
this.cancelEntrust(item);
})
.catch(() => {});
},
//
cancelEntrust(item) {
let data = {
entrust_id: item.id,
entrust_type: item.entrust_type,
symbol: item.symbol,
};
Order.stockcancelEntrust(data).then(() => {
this.$toast.success(this.$t('exchange.g6'));
this.$refs.list.list.forEach((ele, idx) => {
if (item.id == ele.id) {
this.$refs.list.list.splice(idx, 1);
}
});
});
},
}
}
</script>
<style lang="scss" scoped>
.active{
position: relative;
// border-bottom: 1px solid $theme-1;
}
.active:after{
position: absolute;
content: "";
width: 30%;
height: 2px;
background-color: $theme-1;
bottom: 0;
left: 35%;
}
.w-50{
width: 50%;
}
</style>

60
pages/stockexchange/history-commisson.vue

@ -0,0 +1,60 @@
<template>
<v-paging :ajax="getHistoryEntrust">
<template #box="list">
<not-data v-if="!$list(list).length"></not-data>
<div v-for="item in $list(list)" class="item bg-panel-4 m-md rounded-sm box-shadow" :key="item.order_no">
<div class="head d-flex align-center border-b p-x-md p-y-xs justify-between">
<div class="d-flex">
<div v-if="item.entrust_type==1" class="suatus color-buy fn-20 m-r-xs rounded">{{$t('exchange.b5')}}</div>
<div v-if="item.entrust_type==2" class="suatus color-sell fn-20 m-r-xs rounded">{{$t('exchange.b6')}}</div>
<div>
<div class="color-light fn-20">{{item.symbol}}</div>
<div class="fn-10">{{item.created_at}}</div>
</div>
</div>
<div>{{item.status_text}}</div>
</div>
<div class="p-x-md p-y-xs">
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b7')}}</div>
<div class="color-light">{{item.entrust_price}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.b8')}}</div>
<div class="color-light">
<template v-if="item.type==1">{{$t('exchange.b9')}}</template>
<template v-if="item.type==2">{{$t('exchange.c0')}}</template>
</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c1')}}</div>
<div class="color-buy">{{item.traded_amount}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.e2')}}</div>
<div class="color-buy">{{(item.traded_money/item.traded_amount).toFixed(4)*1||'--'}}</div>
</div>
<div class="row d-flex m-y-xs justify-between">
<div class="label fn-sm">{{$t('exchange.c2')}}</div>
<div class="color-light">{{item.amount}}</div>
</div>
</div>
</div>
</template>
</v-paging>
</template>
<script>
import Order from "@/api/order";
import math from '@/utils/class/math'
export default {
data(){
return {
getHistoryEntrust: Order.getstockHistoryEntrust,
}
},
methods:{
division:math.division
}
}
</script>

566
pages/stockexchange/index.vue

@ -0,0 +1,566 @@
<template>
<v-page>
<v-header :leftClick="() => {}" :left-arrow="false">
<template #left>
<view @click="$back(-1)">
<i class="van-icon van-icon-arrow-left van-nav-bar__arrow"></i>
</view>
<view
class="fn-20 color-light m-l-xs"
@click.stop="symbolListShow = true"
>
<i class="iconfont color-theme-1">&#xe655;</i>
{{ query.code }}
</view>
</template>
<template #right>
<view class="fn-lg" @click="option">
<van-icon v-if="isCoolect" class="color-theme-1" name="star" />
<van-icon v-else name="star-o" />
</view>
</template>
</v-header>
<view class="layout-main">
<view
class="price-data d-flex p-t-xs p-x-md justify-between bg-panel-3 rounded-xs"
>
<view class="col">
<view class="num fn-26 color-light">
{{ activeCoin.price }}
</view>
<view class="d-flex">
<view
class="m-l-xs fn-20"
:class="activeCoin.increase < 0 ? 'color-sell' : 'color-buy'"
>
{{ activeCoin.increaseStr }}
</view>
</view>
</view>
<view class="col fn-right justify-center d-flex flex-col">
<table>
<tr>
<td>24h {{ $t("exchange.e3") }}</td>
<td class="color-light">{{ activeCoin.high }}</td>
</tr>
<tr>
<td>24h {{ $t("exchange.e4") }}</td>
<td class="color-light">{{ activeCoin.low }}</td>
</tr>
<tr v-if="!query.contract">
<td>24h {{ $t("exchange.e5") }}</td>
<!-- <td class="color-light">{{ (activeCoin.vol).toFixed(4)}}</td> -->
<td class="color-light">{{activeCoin.vol}}</td>
</tr>
</table>
</view>
</view>
<van-tabs
:border="false"
:active="activeTime"
animated
:ellipsis="false"
@change="tabInterval($event.detail.name)"
>
<van-tab
v-for="item in resolutions"
:name="item.value"
:title="item.label"
:key="item.label"
>
</van-tab>
</van-tabs>
<view class="chart-box">
<iframe
class="chart-tradingview"
:src="`${mobileBase}static/tradingview.html?${setQuery(
iframeQuery
)}`"
></iframe>
</view>
<van-tabs
animated
swipeable
v-model="active"
sticky
:ellipsis="false"
offset-top="1.22667rem"
>
<van-tab :title="$t('exchange.e6')">
<sale :buyList="buyList" :sellList="sellList" :query="query"/>
</van-tab>
<van-tab :title="$t('exchange.d3')">
<latest-transaction :tradeList="tradeList" />
</van-tab>
<van-tab :title="$t('exchange.e7')">
<coin-info :query="query" />
</van-tab>
</van-tabs>
</view>
<!-- 左侧的弹窗 -->
<van-popup
class="bg-panel-4"
:show="symbolListShow"
@close="symbolListShow = false"
close-on-popstate
position="left"
custom-style="height:100%;width:70%"
>
<symbol-list
:collect="collect"
:marketList="marketList"
:title="query.contract ? $t('contract.a4') : ''"
@check-symbol="checkSymbol"
/>
</van-popup>
<view class="btn-group d-flex p-md">
<v-button
block
class="flex-fill m-r-md rounded-lg"
type="green"
replace
:to="{
path: '/pages/base/index',
query: {
symbol: query.code,
direction: 'buy',
tel: query.contract ? 'contract' : 'exchange-operation',
},
}"
>{{ $t("exchange.c3") }}</v-button
>
<v-button
block
class="flex-fill rounded-lg"
type="blue"
replace
:to="{
path: '/pages/base/index',
query: {
symbol: query.code,
direction: 'sell',
tel: query.contract ? 'contract' : 'exchange-operation',
},
}"
>{{ $t("exchange.c4") }}</v-button
>
</view>
<van-toast id="van-toast" />
</v-page>
</template>
<script>
import sale from "./sale";
import symbolList from "./symbol-list";
import latestTransaction from "./latest-transaction";
import coinInfo from "./coin-info";
import Market from "@/api/market";
import Contract from "@/api/contract";
import Home from "@/api/home";
import { mapState } from "vuex";
import math from "@/utils/class/math";
import Exchange from "@/api/exchange";
import qs from "qs";
import app from "app.js";
// 使
let ajaxExchangeMap = {
getMarketList: Market.getstockMarketList,
getBooks: Market.getstockBooks,
sell: "sellList_",
sellList: "sellList",
buy: "buyList_",
buyList: "buyList",
trade: "tradeList_",
tradeList: "tradeList",
market: "exchangeMarketList",
getSymbol(name) {
return name;
},
};
let contractExchangeMap = {
getMarketList: Contract.getMarketList,
getBooks: Contract.getMarketInfo,
sell: "swapSellList_",
sellList: "swapSellList",
buy: "swapBuyList_",
buyList: "swapBuyList",
trade: "swapTradeList_",
tradeList: "swapTradeList",
market: "swapMarketList",
getSymbol(name) {
return name.split("/")[0];
},
};
export default {
components: {
sale,
symbolList,
latestTransaction,
coinInfo,
},
data() {
return {
timeFilter: false,
indexFilter: false,
symbolListShow: false,
active: 0,
buyList: [],
sellList: [],
tradeList: [],
activeTime: "1D",
// activeTime: "60",
index: "",
marketList: [],
collect: [],
unSymbol: "",
query: {},
isLoad: false,
isShow: true,
price_cny: 0,
app
};
},
watch: {
timeFilter(n) {
if (n) this.indexFilter = false;
},
indexFilter(n) {
if (n) this.timeFilter = false;
},
},
computed: {
resolutions() {
let arr = [
{
label: "1" + this.$t("exchange.e8"),
value: "1",
},
{
label: "5" + this.$t("exchange.e8"),
value: "5",
},
{
label: "15" + this.$t("exchange.e8"),
value: "15",
},
{
label: "30" + this.$t("exchange.e8"),
value: "30",
},
{
label: "1" + this.$t("exchange.e9"),
value: "60",
},
// {
// label: "4" + this.$t("exchange.e9"),
// value: "240",
// },
{
label: "1" + this.$t("exchange.f0"),
value: "1D",
},
{
label: "1" + this.$t("exchange.f1"),
value: "1W",
},
{
label: "1" + this.$t("exchange.f2"),
value: "1M",
},
];
return arr;
},
activeTimeObj() {
return this.resolutions.find((item) => item.value == this.activeTime);
},
isLogin() {
return Boolean(uni.getStorageSync("token"));
},
// coin
activeCoin() {
if (!this.marketList.length) return {};
let list = [];
this.marketList.forEach((parentItem) => {
parentItem.marketInfoList.forEach((item) => {
list.push(item);
});
});
return list.find((item) => item.pair_name == this.query.code);
},
//
isCoolect() {
return this.collect
.map((item) => item.pair_name)
.includes(this.query.code);
},
...mapState({
socket: "ws",
socket1: "ws1",
socket2: "ws2",
theme:'theme'
}),
ajax() {
return this.query.contract ? contractExchangeMap : ajaxExchangeMap;
},
ws() {
// return this.query.contract ? this.socket1 : this.socket;
return this.query.contract ? this.socket2 : this.socket;
},
iframeQuery() {
if (this.query.contract) {
return {
getLinkUrl: this.app.baseUrl + "/api/app/contract/getKline",
symbol: this.query.code.split("/")[0],
theme: this.theme,
ws: this.app.socketUrl2,
interval: this.activeTime,
resolutions: this.resolutions.map((item) => item.value),
contract: 1,
// lang:uni.getStorageSync('language')||'zh-CN'
lang:'en'
};
} else {
return {
// getLinkUrl: this.app.baseUrl + "/api/app/contract/getKline",
// symbol: this.query.code.split("/")[0],
// theme: this.theme,
// ws: this.app.socketUrl2,
// interval: this.activeTime,
// resolutions: this.resolutions.map((item) => item.value),
// contract: 1,
// lang:uni.getStorageSync('language')||'zh-CN',
lang:'en',
getLinkUrl: this.app.baseUrl + "/api/app/option/getStockKline",
// getLinkUrl: this.app.baseUrl + "/api/app/option/getKline",
symbol: this.query.code,
theme: this.theme,
ws: this.app.socketUrl,
interval: this.activeTime,
resolutions: this.resolutions.map((item) => item.value),
};
}
},
mobileBase() {
// #ifdef APP-PLUS
if (plus.os.name == "Android") {
return "";
} else {
return this.app.mobile+'/';
}
// #endif
// #ifdef H5
return '/';
// #endif
},
},
methods: {
division:math.division,
setQuery: qs.stringify,
omitTo: math.omitTo,
//
tabInterval(idx) {
// if (this.isLoad) return;
// this.isLoad = true;
this.activeTime = idx;
},
//
changeInterval($ev) {
this.activeTime = $ev;
setTimeout(() => {
this.isLoad = false;
}, 300);
},
getBooks() {
this.ajax.getBooks({
symbol: this.ajax.getSymbol(this.query.code),
})
.then((res) => {
this.buyList = res.data[this.ajax.buyList];
this.sellList = res.data[this.ajax.sellList];
this.tradeList = res.data[this.ajax.tradeList];
});
},
//
getMarketList() {
this.ajax.getMarketList().then((res) => {
this.marketList = res.data;
this.linkSocket(this.activeCoin.symbol);
this.symbolListSocket();
});
},
//
getCollect() {
if (!this.isLogin) return;
Home.getCollect()
.then((res) => {
this.collect = res.data || [];
})
.catch(() => {});
},
//
checkSymbol(obj) {
this.symbolListShow = false;
if (obj.pair_name == this.query.code) return;
// this.query = {code:obj.pair_name};
this._router.replace({
path: "/pages/stockexchange/index",
query: { code: obj.pair_name, contract: this.query.contract },
});
this.getBooks();
},
//
option() {
let data = {
pair_name: this.query.code,
};
Home.option(data)
.then((res) => {
this.getCollect();
if (res.data) {
this.$toast(this.$t("exchange.a6"));
} else {
this.$toast(this.$t("exchange.a7"));
}
})
.catch(() => {});
},
//
getCurrencyExCny() {
Exchange.getCurrencyExCny({
coin_name: this.query.code.split("/")[1],
}).then((res) => {
this.price_cny = res.data.price_cny;
});
},
// socket
linkSocket(symbol) {
this.unSymbol = symbol;
// 线
this.ws.send({
cmd: "sub",
msg: `${this.ajax.buy}${symbol}`,
});
// 线
this.ws.send({
cmd: "sub",
msg: `${this.ajax.sell}${symbol}`,
});
//
this.ws.send({
cmd: "sub",
msg: `${this.ajax.trade}${symbol}`,
});
},
//
unLink(symbol) {
// 线
this.ws.send({
cmd: "unsub",
msg: `${this.ajax.buy}${symbol}`,
});
// 线
this.ws.send({
cmd: "unsub",
msg: `${this.ajax.sell}${symbol}`,
});
//
this.ws.send({
cmd: "unsub",
msg: `${this.ajax.trade}${symbol}`,
});
},
// socket
symbolListSocket() {
this.ws.send({
cmd: "sub",
msg: this.ajax.market,
});
},
// socket
socketMessage() {
this.ws.on("message", (res) => {
if (!this.isShow) return;
let { data, sub } = res;
let arr=this.query.code.replace("/","")
let arr1=arr.substring(0,arr.length-4)
let symbol = !this.query.contract?this.query.code.replace("/", "").toLocaleLowerCase():arr1;
if (sub == this.ajax.market) {
this.marketList=JSON.parse(JSON.stringify(data))
}
if (sub == `${this.ajax.buy}${symbol}`) {
this.buyList=JSON.parse(JSON.stringify(data))
}
if (sub == `${this.ajax.sell}${symbol}`) {
this.sellList=JSON.parse(JSON.stringify(data))
}
if (sub == `${this.ajax.trade}${symbol}`) {
this.tradeList.unshift(data);
this.tradeList.pop();
}
});
},
},
onUnload() {
this.isShow = false;
this.unLink(this.unSymbol);
},
onLoad(query) {
this.query = query;
this.isShow = true;
this.getBooks();
this.getMarketList();
this.getCollect();
this.socketMessage();
this.getCurrencyExCny();
},
destroyed() {
this.ws.send({
cmd: "unsub",
msg: this.ajax.market,
});
this.unLink(this.unSymbol);
},
};
</script>
<style lang="scss" scoped>
.price-data {
position: relative;
.filter {
label {
.button {
border: none;
background: none;
&:active {
color: $theme-1;
}
}
input {
display: none;
}
.filter-panel {
position: absolute;
top: 103%;
left: $padding-md;
right: $padding-md;
overflow: hidden;
button {
background: none;
border: none;
&.active,
&:active {
color: $theme-1;
}
}
}
}
}
}
.chart-tradingview {
height: 370px;
width: 100%;
}
</style>

46
pages/stockexchange/latest-transaction.vue

@ -0,0 +1,46 @@
<template>
<table class="w-max">
<thead>
<tr class="fn-sm">
<th class="p-l-md p-y-xs fn-left">{{$t('exchange.d4')}}</th>
<th class="fn-left">{{$t('exchange.d5')}}</th>
<th class="fn-right">{{$t('exchange.d2')}}</th>
<th class="p-r-md p-y-xs fn-right">{{$t('exchange.c5')}}</th>
</tr>
</thead>
<tbody class="color-light">
<tr v-for="(item,idx) in tradeList" :key="idx">
<td class="p-l-md p-y-xs">{{parseTime(item.ts,false,'{h}:{i}:{s}')}}</td>
<td>
<span class="color-buy" v-if="item.direction=='buy'">
{{$t('exchange.b5')}}
</span>
<span class="color-sell" v-else>
{{$t('exchange.b6')}}
</span>
</td>
<td class="fn-right">{{item.price}}</td>
<td class="p-r-md p-y-xs fn-right">{{omitTo(item.amount,8)*1}}</td>
</tr>
</tbody>
</table>
</template>
<script>
import math from "@/utils/class/math";
import date from "@/utils/class/date";
export default {
props: {
tradeList: {
default() {
return [];
},
type: Array,
required: false,
},
},
methods:{
parseTime:date.parseTime,
omitTo:math.omitTo,
}
};
</script>

92
pages/stockexchange/sale.vue

@ -0,0 +1,92 @@
<template>
<div>
<!-- 深度图 -->
<!-- <div class="depth-map">
<depth-map :serveSellList="sellList" :serveBuyList="buyList" />
</div> -->
<div class="d-flex fn-sm buy-and-sell">
<div :class="query.code!='GITP/USDT'?'w-6/12 buy':'w-12/12 buy'">
<div class="d-flex justify-between p-xs">
<div>{{$t('exchange.c5')}}</div>
<div>{{$t('exchange.f3')}}</div>
</div>
<div class="d-flex item justify-between p-xs" v-for="(item,idx) in buyList" :key="idx">
<div class="progress bg-buy-transparent transition-default" :style="{width:getValue(item.amount)+'%'}"></div>
<div class="color-light">{{item.amount}}</div>
<div class="color-buy">{{item.price}}</div>
</div>
</div>
<div class="w-6/12 sell">
<div class="d-flex justify-between p-xs">
<div>{{$t('exchange.c5')}}</div>
<div>{{$t('exchange.f4')}}{{sellList.length}}</div>
</div>
<div class="d-flex item justify-between p-xs" v-for="(item,idx) in sellList" :key="idx">
<div class="progress bg-sell-transparent transition-default" :style="{width:getValue(item.amount)+'%'}"></div>
<div class="color-light">{{item.amount}}</div>
<div class="color-sell">{{item.price}}</div>
</div>
</div>
</div>
</div>
</template>
<script>
import depthMap from "./depth-map";
import math from "@/utils/class/math";
export default {
props: {
sellList: {
default() {
return [];
},
type: Array,
},
buyList: {
default() {
return [];
},
type: Array,
},
query:{
default:{}
}
},
components: {
depthMap,
},
methods: {
// /
getValue(amount) {
const arr = this.buyList.concat(this.sellList).map((item) => item.amount);
let max = Math.max(...arr);
return math.division(amount, max, 2) * 100;
},
},
mounted() {
},
};
</script>
<style lang="scss" scoped>
.buy-and-sell {
.item {
position: relative;
.progress {
position: absolute;
height: 100%;
top: 0;
}
}
.buy {
.progress {
left: 0;
}
}
.sell {
.progress {
right: 0;
}
}
}
</style>

132
pages/stockexchange/sell-and-buy.vue

@ -0,0 +1,132 @@
<template>
<div class="p-l-xs d-flex flex-col dep-list">
<!-- -->
<div class="d-flex justify-between fn-xs m-b-xs">
<span>{{$t('exchange.d2')}}</span>
<span>{{$t('exchange.c5')}}</span>
</div>
<div class=" overflow-scroll rotatebox" v-if="symbol!='GITP/USDT'">
<div class="rotateZ">
<div
class="d-flex justify-between h-24 align-center row"
v-for="(item,idx) in showSellList"
:key="idx"
@click="$emit('price',item.price)"
>
<span class="color-sell">{{item.price}}</span>
<!-- <span class="color-sell" v-if="item.price>100">{{omitTo(item.price,2)}}</span>
<span class="color-sell" v-if="item.price>1&&item.price<100">{{omitTo(item.price,4)}}</span>
<span class="color-sell" v-if="item.price<1">{{omitTo(item.price,6)}}</span> -->
<span class="p-r-xs">{{omitTo(item.amount,2)}}</span>
<div
class="proagess h-max bg-sell-transparent"
:style="{width:getValue(item.amount)+'%'}"
>
</div>
</div>
</div>
</div>
<div class="border-t border-b p-y-xs">
<slot/>
</div>
<div class=" overflow-scroll">
<div
class="d-flex justify-between h-24 align-center row"
v-for="(item,idx) in showBuyList"
:key="idx"
@click="$emit('price',item.price)"
>
<span class="color-buy">{{item.price}}</span>
<!-- <span class="color-buy" v-if="item.price>100">{{omitTo(item.price,2)}}</span>
<span class="color-buy" v-if="item.price>1&&item.price<100">{{omitTo(item.price,4)}}</span>
<span class="color-buy" v-if="item.price<1">{{omitTo(item.price,6)}}</span> -->
<span class="p-r-xs">{{omitTo(item.amount,2)}}</span>
<div class="proagess h-max bg-buy-transparent" :style="{width:getValue(item.amount)+'%'}"></div>
</div>
</div>
</div>
</template>
<script>
import date from "@/utils/class/date";
import math from "@/utils/class/math";
export default {
name: "buy-and-sell",
props: {
buyList: {
default:()=> [],
required: true,
type: Array,
},
sellList: {
default: ()=>[],
required: true,
type: Array,
},
max:{
default:undefined,
type:Number,
required:false
},
contract:{
default:undefined,
type:Number,
required:false
},
symbol: {
default: undefined,
type: String,
required: false,
},
},
components: {},
computed: {
showBuyList(){
if(this.max){
return this.buyList.splice(0,this.max)
}
return this.buyList
},
showSellList(){
if(this.max&&this.contract==1){
return this.sellList.splice(this.sellList.length-this.max,this.max)
}
if(this.max&&this.contract==0){
return this.sellList.splice(0,this.max)
}
return this.sellList
}
},
mounted() {
},
methods: {
parseTime: date.parseTime,
omitTo: math.omitTo,
//
getValue(amount) {
const arr = this.showBuyList.concat(this.showSellList).map((item) => item.amount);
let max = Math.max(...arr);
return math.division(amount, max, 2) * 100;
},
},
};
</script>
<style lang="scss" scoped>
.dep-list {
max-height: 456px;
.row {
position: relative;
.proagess {
position: absolute;
right: 0;
top: 0;
transition: width 0.3s;
}
}
}
.rotatebox {
transform: rotateZ(-180deg);
.rotateZ {
transform: rotateZ(180deg);
}
}
</style>

177
pages/stockexchange/symbol-list.vue

@ -0,0 +1,177 @@
<template>
<view class="symbol-list">
<view class="w-max" style="height: var(--status-bar-height)"></view>
<view class="title fn-18 p-md color-light">{{ title||$t("exchange.f5") }}</view>
<van-search
background="transparent"
:value="filterText"
@change="filterText = $event.detail"
:placeholder="$t('exchange.f6')"
/>
<van-tabs :active="active">
<van-tab
:title="heyue==1&&parentItem.coin_name=='USDT'?$t('first.b8'):parentItem.coin_name"
v-for="parentItem in showMarketList"
:key="parentItem.coin_name"
>
<view class="p-x-xs m-t-md">
<table class="w-max">
<thead v-if="heyue==0">
<tr class="fn-sm">
<th class="p-l-md p-y-xs fn-left">{{ $t("exchange.f7") }}</th>
<th class="fn-left">{{ $t("exchange.f8") }}</th>
<th class="p-r-md p-y-xs fn-right">{{ $t("exchange.f9") }}</th>
</tr>
</thead>
<tbody>
<tr
class="p-y-md"
:class="symbols==item.coin_name&&heyue==1?'bg-panel':''"
v-for="item in parentItem.marketInfoList"
:key="item.symbol"
v-show="isShow(item.pair_name)"
@click="$emit('check-symbol', item)"
>
<td class="p-l-md p-y-md w-40">
<template v-if="parentItem.isCollect">
<span class="color-light">{{ item.pair_name }}</span>
</template>
<template v-else>
<span class="color-light">{{ item.coin_name||item.symbol }}/{{ parentItem.coin_name }}</span>
</template>
</td>
<td class="w-30 fn-center">
<template v-if="heyue==0" :class="item.increase < 0 ? 'color-sell' : 'color-buy'">
{{ item.price }}
</template>
<template v-else>
{{$t('first.b8')}}
</template>
</td>
<td
v-if="heyue==0"
:class="item.increase < 0 ? 'color-sell' : 'color-buy'"
class="p-r-md p-y-xs fn-right w-30"
>
{{ item.increaseStr }}
</td>
<td
v-if="heyue==1"
:class="item.increase < 0 ? 'color-sell' : 'color-buy'"
class="p-r-md p-y-xs fn-right"
>
{{ item.price }}
</td>
</tr>
</tbody>
</table>
</view>
</van-tab>
</van-tabs>
</view>
</template>
<script>
export default {
props: {
marketList: {
default() {
return [];
},
type: Array,
required: false,
},
collect: {
default() {
return [];
},
type: Array,
required: false,
},
title:{
default:''
},
heyue:{
default: 1,
type: Number,
required: false,
},
symbols:{
default: '',
type: String,
required: false,
}
},
computed: {
showMarketList() {
let collect = this.collect.map((item) => item.pair_name);
let collects = [];
this.marketList.forEach((parentItem) => {
// if(this.contract==1&&parentItem.coin_name=='USDT'){
// parentItem.coin_name=this.$t('first.b8')
// }
// console.log(parentItem.coin_name,this.contract)
parentItem.marketInfoList.forEach((item) => {
if (collect.includes(item.pair_name)) {
collects.push(item);
}
});
});
let arr = [
...this.marketList,
{
coin_name: this.$t("exchange.g0"),
isCollect: true,
marketInfoList: collects,
},
];
// console.info(arr)
return arr;
},
},
data() {
return {
active: 0,
filterText: "",
};
},
methods: {
isShow(str) {
return (
str.toLocaleLowerCase().indexOf(this.filterText.toLocaleLowerCase()) !=
-1
);
},
},
created() {},
};
</script>
<style lang="scss" scoped>
.table-list {
tr:nth-of-type(2n-1) {
td {
background: $panel-3;
}
}
}
/deep/ .van-tabs__line::before{
width: 35px;
height: 2px;
border-radius:5px;
background-color: $theme-1;
}
table{
border-collapse:collapse
}
.w-40{
width: 40%;
}
.w-30{
width: 30%;
}
.w-30{
width: 30%;
}
</style>

339
pages/stockexchange/time-sharing.vue

@ -0,0 +1,339 @@
<template>
<div id="chart122" :prop="config" :change:prop="highstock.changeConfig" class="chart-box"></div>
</template>
<script>
import { mapState } from "vuex";
export default {
props: {
tradeList: {
default() {
return [];
},
type: Array,
required: false,
},
query: {
default: {},
type: Object,
required: false,
},
},
computed: {
...mapState({
serveTheme: "theme",
}),
},
watch: {},
data() {
return {
config: {},
};
},
methods: {
resetData(){
this.config = '';
this.$nextTick(()=>{
this.config = {
type:'resetList',
list:this.tradeList,
date:new Date()
}
})
},
addPoint(data){
this.config = {
type:'addPoint',
point:data,
date:new Date()
}
},
getConfig() {
return {
type: "initPage",
list: this.tradeList,
theme:this.serveTheme
};
},
},
created() {
this.config = this.getConfig();
},
};
</script>
<script module="highstock" lang="renderjs">
import highstock from "highcharts/highstock";
export default {
computed: {
list() {
return this.chartTradList.map((item) => {
return [item.ts, item.price*1];
});
},
},
watch: {},
data() {
return {
chart: undefined,
chartTradList:[],
theme:'light'
};
},
methods: {
changeConfig(config){
this.task(config)
},
task(config){
switch (config.type) {
case 'resetList':
this.chartTradList = config.list;
this.setData(this.list)
break;
case 'addPoint':
this.webAddPoint(config.point)
break;
case 'initPage':
this.chartTradList = config.list;
this.theme = config.theme;
break;
default:
break;
}
},
isDSTByRules() {
const now = new Date();
const year = now.getUTCFullYear();
// 3 2:00 AM EDT
const dstStart = this.getNthSunday(year, 2, 2, 2); // 0 2=3
// 11 2:00 AM EST
const dstEnd = this.getNthSunday(year, 10, 1, 2); // 0 10=11
return now >= dstStart && now < dstEnd;
},
// nm0
getNthSunday(year, month, occurrence, hour) {
if (month === 10 && occurrence === 1) {
const date = new Date(year, 10, 3); // 113
date.setHours(hour, 0, 0, 0);
return date;
}
let date = new Date(year, month, 1);
let count = 0;
while (true) {
if (date.getDay() === 0) {
if (++count === occurrence) {
date.setHours(hour);
return date;
}
}
date.setDate(date.getDate() + 1);
}
},
intiChart($box) {
let timeData = this.isDSTByRules()
highstock.setOptions({
global: {
timezoneOffset: timeData ? 16 * 60 : 16 * 60,
},
});
this.chart = highstock.stockChart($box, {
chart: {
marginTop: 0,
// marginLeft: 0,
marginBottom: 20,
padding: 0,
panning: false, //
pinchType: "", //
zoomType: "",
panKey: "shift",
backgroundColor: "transparent",
borderColor: "transparent",
borderWidth: "1",
plotBackgroundColor: "transparent",
Point: {
visible: !1,
},
},
rangeSelector: {
enabled: false,
},
navigator: {
enabled: false,
},
scrollbar: {
enabled: false,
},
exporting: {
enabled: !0,
},
credits: {
enabled: !1,
},
mapNavigation: {
enabled: !1,
enableButtons: !1,
},
navigation: {
enabled: !1,
buttonOptions: {},
},
title: {
text: null,
},
yAxis: {
gridLineWidth: 1,
tickWidth: 0,
tickColor: "#22222d",
tickAmount: 7,
// lineWidth: 1,
lineColor: "#1E2E3F",
labels: {
align: "center",
x: 0,
style: {
color: this.theme=='light'?"#333":"#dcdee0",
fontSize: "8px",
},
useHTML: !0,
formatter: (ev) => {
return this.nFormatter(ev.value, 3);
},
},
opposite: false,
gridLineColor: "transparent",
},
xAxis: {
type: "datetime",
dateTimeLabelFormats: {
millisecond: "%H:%M:%S.%L",
second: "%H:%M:%S",
minute: "%H:%M",
hour: "%H:%M",
day: "%m-%d",
week: "%m-%d",
month: "%Y-%m",
year: "%Y",
},
tickWidth: 0,
lineWidth: "0",
tickLength: 0,
labels: {
style: {
color: this.theme=='light'?"#333":"#dcdee0",
fontSize: "10px",
},
y: 10,
},
},
tooltip: {
enabled: false,
dateTimeLabelFormats: {
millisecond: "%H:%M:%S.%L",
second: "%H:%M:%S",
minute: "%H:%M",
hour: "%H:%M",
day: "%Y-%m-%d",
week: "%m-%d",
month: "%Y-%m",
year: "%Y",
},
},
legend: {
enabled: !1,
},
plotOptions: {
areaspline: {
allowPointSelect:false,
fillColor: {
linearGradient: {
x1: 0,
y1: 0,
x2: 0,
y2: 1,
},
stops: [
[0, "rgba(192,96,194,.58)"],
[1, "rgba(90,99,251,.13)"],
],
},
marker: {
radius: 2,
},
lineWidth: 2,
threshold: null,
},
},
series: [
{
marker: {
radius: 0,
lineWidth: 0,
lineColor: "#fba845",
fillColor: "#fba845",
states: {},
},
type: "areaspline",
name: "",
data: this.list,
color: {
linearGradient:{
x1:'0%',
y1:'0%',
x2:'100%',
y2:'100%'
},
stops:[
[0, '#C060C2'],
[1, '#5A63FB'],
]
},
},
],
});
},
nFormatter(num, digits) {
const si = [
{ value: 1, symbol: "" },
{ value: 1e3, symbol: "K" },
{ value: 1e6, symbol: "M" },
{ value: 1e9, symbol: "G" },
{ value: 1e12, symbol: "T" },
{ value: 1e15, symbol: "P" },
{ value: 1e18, symbol: "E" },
];
const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
let i;
for (i = si.length - 1; i > 0; i--) {
if (num >= si[i].value) {
break;
}
}
return (
(num / si[i].value).toFixed(digits).replace(rx, "$1") + si[i].symbol
);
},
setData(arr) {
if(this.chart) this.chart.series[0].setData(arr);
},
webAddPoint(obj){
if(this.chart) this.chart.series[0].addPoint(obj,true,true)
}
},
mounted() {
this.task(this.config)
this.intiChart(document.getElementById("chart122"));
},
destroyed() {},
};
</script>
<style lang="scss" scoped>
.chart-box {
height: 100%;
}
</style>
Loading…
Cancel
Save