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

1121 lines
34 KiB

<template>
<view class="market_index">
<view class="market_head" :class="{ market_head1: isUnfold }">
<view class="market_head_top">
<view class="closed_price" @tap="collection">
<view class="closed_price_top">
<view
class="closed_price_text colorGreen"
:class="{ colorRed: data.changePercentage > 0 }"
>{{ data.closingPrice }}</view
>
<u-icon v-if="!isCollection" name="star" size="20"></u-icon>
<u-icon v-else name="star-fill" size="20" color="#EC7C00"></u-icon>
</view>
<view
class="closed_price_bottom colorGreen"
:class="{ colorRed: data.changePercentage > 0 }"
>{{ data.cha.toFixed(2) }} [{{
data.changePercentage.toFixed(2)
}}%]</view
>
</view>
<view class="closed_opening">
<view style="margin-top: 4rpx">
<text class="head_text">开</text>
<text class="head_num">{{ data.openingPrice }}</text>
</view>
<view style="margin-top: 20rpx">
<text class="head_text">收</text>
<text class="head_num">{{ data.closingPrice }}</text>
</view>
</view>
<view class="quantity_quota" @tap="unfold">
<view style="margin-top: 4rpx">
<text class="head_text">量</text>
<text class="head_num">{{ data.volume }}</text>
</view>
<view style="margin-top: 20rpx">
<text class="head_text">额</text>
<text class="head_num">{{ data.turnover }}</text>
</view>
</view>
<view @tap="unfold">
<image
src="../../../static/zhan.png"
v-if="!isUnfold"
style="width: 32rpx; height: 32rpx"
mode="scaleToFill"
/>
<image
v-else
src="../../../static/show.png"
style="width: 32rpx; height: 32rpx"
mode="scaleToFill"
/>
</view>
</view>
</view>
<view class="line"> </view>
<view style="height: 1100rpx; padding: 0 20rpx; width: 710rpx">
<l-echart ref="chartK"></l-echart>
</view>
<view class="nav_list">
<text
v-for="(item, index) in navList"
:key="index"
class="nav_list_text"
:class="{ nav_list_text1: item.is }"
@tap="selectNav(item.name)"
>
{{ item.name }}
</text>
</view>
<view v-if="!showLoad">
<view v-if="navList[0].is">
<view>
<l-echart ref="columnar"></l-echart>
</view>
</view>
<view v-else>
<view class="private_table_head">
<view class="private_table_head_left">
<view class="private_head_name">股票名称</view>
<view class="private_head_price">价格</view>
<view class="private_head_gains">涨幅</view>
</view>
<view class="private_table_head_right">
<view>{{ currentBelong }}</view>
<!-- <image
src="../static/jiangxu_false.png"
class="private_screening_icon"
mode="scaleToFill"
/> -->
</view>
</view>
<view v-if="list.length > 0">
<view
class="private_table_list"
v-for="(item, index) in list"
:key="index"
>
<view class="private_table_list_left">
<view class="table_list_name">
<view>{{ item.securityName }}</view>
<view class="table_list_code">{{ item.securityCode }}</view>
</view>
<view
class="table_list_price"
:class="{ table_list_price1: item.changePercentage < 0 }"
>
{{ item.closingPrice }}
</view>
<view
class="table_list_gains"
:class="{ table_list_price1: item.changePercentage < 0 }"
>
{{ item.changePercentage.toFixed(2) }}
</view>
</view>
<view>{{ item.dongCaiIndustryIndexLevel2 }}</view>
</view>
</view>
<view v-else>
<u-empty
mode="data"
icon="http://cdn.uviewui.com/uview/empty/data.png"
marginTop="50"
>
</u-empty>
</view>
</view>
<!-- <view
class="list_footer"
v-if="list.length > 10 && !navList[0].is"
@tap="toTrendDetail"
>
<view class="see_more">
<view>查看更多</view>
<image
src="../static/chakangengduo.png"
class="see_more_icon"
mode="scaleToFill"
/>
</view>
</view> -->
</view>
<view v-else class="show_load">
<u-loading-icon></u-loading-icon>
</view>
<u-popup :show="isUnfold" mode="top">
<view class="market_head" :class="{ market_head1: isUnfold }">
<view class="market_head_top">
<view class="closed_price" @tap="collection">
<view class="closed_price_top">
<view
class="closed_price_text colorGreen"
:class="{ colorRed: data.changePercentage > 0 }"
>{{ data.closingPrice }}</view
>
<u-icon v-if="!isCollection" name="star" size="20"></u-icon>
<u-icon
v-else
name="star-fill"
size="20"
color="#EC7C00"
></u-icon>
</view>
<view
class="closed_price_bottom colorGreen"
:class="{ colorRed: data.changePercentage > 0 }"
>{{ data.cha.toFixed(2) }} [{{
data.changePercentage.toFixed(2)
}}%]</view
>
</view>
<view class="closed_opening">
<view style="margin-top: 4rpx">
<text class="head_text">开</text>
<text class="head_num">{{ data.openingPrice }}</text>
</view>
<view style="margin-top: 20rpx">
<text class="head_text">收</text>
<text class="head_num">{{ data.closingPrice }}</text>
</view>
</view>
<view class="quantity_quota" @tap="unfold">
<view style="margin-top: 4rpx">
<text class="head_text">量</text>
<text class="head_num">{{ data.volume }}</text>
</view>
<view style="margin-top: 20rpx">
<text class="head_text">额</text>
<text class="head_num">{{ data.turnover }}</text>
</view>
</view>
<view @tap="unfold">
<image
src="../../../static/zhan.png"
v-if="!isUnfold"
style="width: 32rpx; height: 32rpx"
mode="scaleToFill"
/>
<image
v-else
src="../../../static/show.png"
style="width: 32rpx; height: 32rpx"
mode="scaleToFill"
/>
</view>
</view>
<view class="market_head_bottom">
<view class="head_bottom_list">
<view class="security_code">
<view class="bottom_list_text"> 证券代码 </view>
<view class="bottom_list_num">{{ data.securityCode }}</view>
</view>
<view class="trade_date">
<view class="bottom_list_text"> 交易日 </view>
<view class="bottom_list_num">{{ data.businessDate }}</view>
</view>
<view class="opening_high">
<view class="bottom_list_text"> 最高 </view>
<view class="bottom_list_num">{{ data.highestPrice }}</view>
</view>
<view class="opening_less">
<view class="bottom_list_text"> 最低 </view>
<view class="bottom_list_num">{{ data.lowestPrice }}</view>
</view>
</view>
<view class="head_bottom_list">
<view class="security_code">
<view class="bottom_list_text"> 涨跌幅 </view>
<view class="bottom_list_num"
>{{ data.changePercentage.toFixed(2) }}%</view
>
</view>
<view class="trade_date">
<view class="bottom_list_text"> 10日涨跌幅 </view>
<view class="bottom_list_num"
>{{ data.rangeRiseLosses10.toFixed(2) }}%</view
>
</view>
<view class="opening_high">
<view class="bottom_list_text"> 20日涨跌幅 </view>
<view class="bottom_list_num"
>{{ data.rangeRiseLosses20.toFixed(2) }}%</view
>
</view>
<view class="opening_less">
<view class="bottom_list_text"> 60日涨跌幅 </view>
<view class="bottom_list_num"
>{{ data.rangeRiseLosses60.toFixed(2) }}%</view
>
</view>
</view>
<view class="head_bottom_list">
<view class="security_code">
<view class="bottom_list_text"> 流通 </view>
<view class="bottom_list_num">{{ data.freeCapitalization }}</view>
</view>
<view class="trade_date">
<view class="bottom_list_text"> 20日区间平均成交量 </view>
<view class="bottom_list_num">{{ data.averageVolumeDay20 }}</view>
</view>
</view>
</view>
</view>
</u-popup>
<!-- 个股所属板块 -->
<u-picker
:show="showPrivateBelong"
:columns="columnsBelong"
cancelColor="#EC7C00"
confirmColor="#EC7C00"
@cancel="cancelPrivateBelong"
@confirm="confirmPrivateBelong"
></u-picker>
</view>
</template>
<script>
import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
export default {
data() {
return {
showLoad: false,
// 个股所属板块
showPrivateBelong: false,
currentBelong: '所属板块',
columnsBelong: [['所属板块', '成交量']],
isCollection: false,
isUnfold: false,
navList: [
{
name: '涨跌区间',
is: true,
},
{
name: '涨停个股',
is: false,
},
{
name: '跌停个股',
is: false,
},
],
list: [],
navId: '',
date: '',
marketType: '',
marketCode: '',
data: {},
pagenum: 1,
last_page: null,
}
},
onLoad(options) {
uni.setNavigationBarTitle({
title: options.name,
})
this.rendingType(options.name)
this.queryCollection()
this.date = options.date
this.rending()
},
onReachBottom() {
if (this.pagenum < this.last_page) {
this.getnewGoods()
}
},
mounted() {
this.$nextTick(() => {
// 执行echarts方法
this.initEcharts()
this.columnarInitCharts()
})
},
methods: {
unfold() {
this.isUnfold = !this.isUnfold
},
rending() {
this.$api
.post('/stock/appBigDetail', {
businessDate: this.date,
// businessDate: '',
securityCode: this.marketCode,
// securityCode: '000001',
securityType: this.marketType,
// securityType: 'SH',
})
.then(r => {
if (r) {
this.data = r.originalIssueStock
this.data.cha = this.data.closingPrice - this.data.openingPrice
}
})
.catch(fall => {
console.log(fall)
})
},
rendingType(name) {
if (name == '上证指数') {
this.marketType = 'SH'
this.marketCode = '000001'
} else if (name == '深证指数') {
this.marketType = 'SZ'
this.marketCode = '399006'
} else if (name == '创业板') {
this.marketType = '30'
this.marketCode = '399001'
} else if (name == '科创板') {
this.marketType = '688'
this.marketCode = '000688'
}
},
// 查询是否收藏
queryCollection() {
this.$api
.post('/collect/queryIsCollect', {
securityCode: this.marketCode,
})
.then(r => {
if (r) {
r == 1 ? (this.isCollection = true) : (this.isCollection = false)
}
})
.catch(fall => {
console.log(fall)
})
},
getRoseOrFall() {
this.$api
.post('/stock/riseLossesDetail', {
businessDate: this.date,
pageModel: {
pageNo: this.pagenum,
pageSize: 20,
sortField: '',
sortWay: '',
},
riseOrLosses: this.navId,
securityCode: this.marketCode,
securityType: this.marketType,
})
.then(r => {
if (r) {
this.list = r.list
this.showLoad = false
this.last_page = r.totalPage
// this.data = r
}
})
.catch(fall => {
console.log(fall)
})
},
getRoseOrFall1() {
this.$api
.post('/stock/riseLossesDetail', {
businessDate: this.date,
pageModel: {
pageNo: this.pagenum,
pageSize: 20,
sortField: '',
sortWay: '',
},
riseOrLosses: this.navId,
securityCode: this.marketCode,
securityType: this.marketType,
})
.then(r => {
if (r) {
this.list = [...this.list, ...r.list]
this.showLoad = false
this.last_page = r.totalPage
// this.data = r
}
})
.catch(fall => {
console.log(fall)
})
},
getnewGoods() {
this.pagenum = this.pagenum + 1
// 1.展示loading效果
uni.showLoading({
title: '数据加载中...',
})
// 2.开启节流阀
this.isLoading = true
// 3.发起网络请求
this.getRoseOrFall1()
// 无论成功与否都会调用该方法
// 4.隐藏loading效果
uni.hideLoading()
// 5.关闭节流阀
this.isLoading = false
},
// 选择导航
selectNav(name) {
this.pagenum = 1
this.showLoad = true
this.navList.forEach((item, index) => {
if (item.name == name) {
item.is = true
if (this.navList[1].is) {
this.navId = 1
this.getRoseOrFall()
} else if (this.navList[2].is) {
this.navId = 0
this.getRoseOrFall()
} else if (this.navList[0].is) {
this.$nextTick(() => {
this.columnarInitCharts()
})
}
// setTimeout(() => {
// this.showLoad = false
// }, 1000)
} else {
item.is = false
}
})
},
// 打开个股所属模块弹出层
privateBelong() {
uni.hideTabBar({})
this.showPrivateBelong = true
},
// 取消个股所属模块弹出层
cancelPrivateBelong() {
this.showPrivateBelong = false
uni.showTabBar({})
},
// 确认个股所属模块
confirmPrivateBelong(e) {
this.currentBelong = e.value[0]
this.showPrivateBelong = false
uni.showTabBar({})
},
// 前往趋势详情
toTrendDetail() {
this.navList.forEach(item => {
if (item.is) {
uni.navigateTo({
url: `/pages/home/market/marketDetail?name=${item.name}`,
})
}
})
},
// 是否收藏
collection() {
// this.isCollection = !this.isCollection
if (this.isCollection) {
this.$api
.post('/collect/del', {
securityCode: this.marketCode,
securityType: this.marketType,
})
.then(r => {
uni.$u.toast('已取消收藏')
this.isCollection = false
})
.catch(fall => {
uni.$u.toast('已取消收藏')
this.isCollection = false
console.log(fall)
})
} else {
this.$api
.post('/collect/add', {
securityCode: this.marketCode,
securityType: this.marketType,
})
.then(r => {
uni.$u.toast('收藏成功')
this.isCollection = true
})
.catch(fall => {
uni.$u.toast('收藏成功')
this.isCollection = true
console.log(fall)
})
}
},
// k线图初始化
initEcharts() {
this.$api
.post('/stock/kLine', {
// securityCode: this.id,
securityCode: this.marketCode,
securityType: '',
})
.then(r => {
if (r) {
// this.data = r
console.log(r)
this.$refs.chartK.init(echarts, chart => {
let upColor = '#ec0000'
let downColor = '#00da3c'
// 数据意义:开盘(open),收盘(close),最低(lowest),最高(highest)
let data = splitData(r)
function splitData(rawData) {
let categoryData = []
let values = []
let volumes = []
for (let i = 0; i < rawData.length; i++) {
categoryData.push(rawData[i].splice(0, 1)[0])
values.push(rawData[i])
volumes.push([
i,
rawData[i][4],
rawData[i][0] > rawData[i][1] ? 1 : -1,
])
}
return {
categoryData: categoryData,
values: values,
volumes: volumes,
}
}
function calculateMA(dayCount) {
let result = []
for (let i = 0, len = data.values.length; i < len; i++) {
if (i < dayCount) {
result.push('-')
continue
}
let sum = 0
for (let j = 0; j < dayCount; j++) {
sum += data.values[i - j][1]
}
result.push(sum / dayCount)
}
return result
}
let option = {
animation: false,
legend: {
top: 10,
left: 'center',
data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30'],
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
formatter: function (param) {
// let param1 = param[1];
if (param[0].data.length < 6) {
param = param[1]
console.log(param)
return [
'日期: ' + param.axisValue + '\n',
'开盘: ' + param.data[1] + '\n',
'关盘: ' + param.data[2] + '\n',
'最低: ' + param.data[3] + '\n',
'最高: ' + param.data[4] + '\n',
'成交额: ' + param.data[5] + '\n',
].join('')
} else {
param = param[0]
console.log(param)
return [
'日期: ' + param.axisValue + '\n',
'开盘: ' + param.data[1] + '\n',
'关盘: ' + param.data[2] + '\n',
'最低: ' + param.data[3] + '\n',
'最高: ' + param.data[4] + '\n',
'成交额: ' + param.data[5] + '\n',
].join('')
}
},
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
textStyle: {
color: '#000',
},
position: function (pos, params, el, elRect, size) {
const obj = {
top: 10,
}
obj[
['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]
] = 30
return obj
},
// extraCssText: 'width: 170px'
},
axisPointer: {
link: [
{
xAxisIndex: 'all',
},
],
label: {
backgroundColor: '#777',
},
},
toolbox: {
feature: {
dataZoom: {
yAxisIndex: false,
},
brush: {
type: ['lineX', 'clear'],
},
},
},
brush: {
xAxisIndex: 'all',
brushLink: 'all',
outOfBrush: {
colorAlpha: 0.1,
},
},
visualMap: {
show: false,
seriesIndex: 5,
dimension: 2,
pieces: [
{
value: 1,
color: upColor,
},
{
value: -1,
color: downColor,
},
],
},
grid: [
{
left: '10%',
right: '8%',
height: '50%',
},
{
left: '10%',
right: '8%',
top: '63%',
height: '16%',
},
],
xAxis: [
{
type: 'category',
data: data.categoryData,
boundaryGap: false,
axisLine: { onZero: false },
splitLine: { show: false },
min: 'dataMin',
max: 'dataMax',
axisPointer: {
z: 100,
},
},
{
type: 'category',
gridIndex: 1,
data: data.categoryData,
boundaryGap: false,
axisLine: { onZero: false },
axisTick: { show: false },
splitLine: { show: false },
axisLabel: { show: false },
min: 'dataMin',
max: 'dataMax',
},
],
yAxis: [
{
scale: true,
splitArea: {
show: true,
},
},
{
scale: true,
gridIndex: 1,
splitNumber: 2,
axisLabel: { show: false },
axisLine: { show: false },
axisTick: { show: false },
splitLine: { show: false },
},
],
dataZoom: [
{
type: 'inside',
xAxisIndex: [0, 1],
start: 0,
end: 100,
},
{
show: true,
xAxisIndex: [0, 1],
type: 'slider',
top: '85%',
start: 0,
end: 100,
},
],
series: [
{
name: '日K',
type: 'candlestick',
data: data.values,
itemStyle: {
color: downColor,
color0: upColor,
borderColor: undefined,
borderColor0: undefined,
},
tooltip: {
formatter: function (param) {
console.log(param)
param = param[0]
return [
'Date: ' +
param.name +
'<hr size=1 style="margin: 3px 0">',
': ' + param.data[0] + '<br/>',
'Close: ' + param.data[1] + '<br/>',
'Lowest: ' + param.data[2] + '<br/>',
'Highest: ' + param.data[3] + '<br/>',
].join('')
},
},
},
{
name: 'MA5',
type: 'line',
data: calculateMA(5, data),
smooth: true,
lineStyle: {
opacity: 0.5,
},
},
{
name: 'MA10',
type: 'line',
data: calculateMA(10, data),
smooth: true,
lineStyle: {
opacity: 0.5,
},
},
{
name: 'MA20',
type: 'line',
data: calculateMA(20, data),
smooth: true,
lineStyle: {
opacity: 0.5,
},
},
{
name: 'MA30',
type: 'line',
data: calculateMA(30, data),
smooth: true,
lineStyle: {
opacity: 0.5,
},
},
{
name: 'Volume',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
itemStyle: {
// normal: {
// color: function (param) {
// return downColor;
// },
// },
},
data: data.volumes,
},
],
}
chart.setOption(option)
})
}
})
.catch(fall => {
console.log(fall)
})
},
// 柱状图初始化
columnarInitCharts() {
this.$api
.post('/stock/riseLossesStatistics', {
businessDate: this.date,
securityCode: '',
securityType: this.marketType,
})
.then(r => {
if (r) {
// this.data = r
this.$refs.columnar.init(echarts, chart => {
let option = {
xAxis: {},
yAxis: {
// type: 'value',
type: 'category',
data: [
'10%',
'7%',
'7-5%',
'5-3%',
'3-0%',
'',
'-3-5%',
'-5-7%',
'-7%',
'-10%',
],
},
series: [
{
data: r.data,
type: 'bar',
itemStyle: {
normal: {
//这里是重点
color: function (params) {
//注意,如果颜色太少的话,后面颜色不会自动循环,最好多定义几个颜色
var colorList = [
'#D9001B',
'#D9001B',
'#D9001B',
'#D9001B',
'#D9001B',
'#999999',
'#6FBB60',
'#6FBB60',
'#6FBB60',
'#6FBB60',
]
return colorList[params.dataIndex]
},
label: {
show: true, //开启显示
position: 'right', //在上方显示
textStyle: {
//数值样式
// color: "black",
fontSize: 14,
},
},
},
},
},
],
grid: {
top: '5%',
},
}
chart.setOption(option)
})
}
})
.catch(fall => {
console.log(fall)
})
},
},
}
</script>
<style lang="scss" scoped>
.show_load {
margin-top: 100rpx;
}
.market_head {
padding: 32rpx 24rpx 0 24rpx;
height: 100rpx;
width: 702rpx;
overflow: hidden;
.closed_price {
font-size: 24rpx;
.closed_price_top {
display: flex;
font-size: 40rpx;
}
}
.closed_price_text {
margin-right: 24rpx;
font-weight: bold;
}
.closed_price_bottom {
margin-top: 10rpx;
}
}
.market_head1 {
height: 100%;
}
.market_head_top {
display: flex;
align-items: center;
justify-content: space-between;
}
.market_head_bottom {
padding-bottom: 32rpx;
}
.head_bottom_list {
margin-top: 32rpx;
display: flex;
align-items: center;
.security_code {
width: 158rpx;
border-right: 2rpx dashed #c8c8c8;
}
.trade_date {
width: 208rpx;
border-right: 2rpx dashed #c8c8c8;
margin-left: 20rpx;
}
.opening_high {
border-right: 2rpx dashed #c8c8c8;
margin-left: 20rpx;
width: 160rpx;
}
.opening_less {
margin-left: 20rpx;
}
.bottom_list_text {
font-size: 24rpx;
color: #999999;
}
.bottom_list_num {
margin-top: 8rpx;
font-size: 28rpx;
}
}
.closed_opening {
font-size: 28rpx;
}
.quantity_quota {
font-size: 28rpx;
}
.head_text {
color: #999999;
}
.head_num {
margin-left: 16rpx;
}
.line {
height: 2rpx;
background-color: #f6f6f6;
margin-top: 32rpx;
}
.nav_list {
padding: 32rpx 24rpx;
color: #999999;
.nav_list_text {
margin-right: 32rpx;
}
.nav_list_text1 {
font-weight: bold;
color: #333333;
}
}
.private_table_head {
display: flex;
align-items: center;
font-size: 24rpx;
font-weight: bold;
background-color: #fff9f3;
padding: 20rpx 24rpx;
justify-content: space-between;
.private_table_head_right {
display: flex;
align-items: center;
}
.private_table_head_left {
display: flex;
align-items: center;
.private_head_name {
width: 200rpx;
}
.private_head_price {
width: 150rpx;
text-align: center;
}
.private_head_gains {
width: 150rpx;
text-align: center;
}
}
}
.private_table_list {
padding: 24rpx 24rpx;
border-bottom: 2rpx solid #f6f6f6;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
.private_table_list_left {
display: flex;
align-items: center;
.table_list_name {
width: 200rpx;
}
.table_list_code {
margin-top: 10rpx;
font-size: 24rpx;
color: #999999;
}
.table_list_price {
width: 150rpx;
text-align: center;
color: #d9001b;
}
.table_list_gains {
width: 150rpx;
text-align: center;
color: #d9001b;
}
table_list_price1 {
color: #8fc320;
}
}
}
.private_screening_icon {
width: 18rpx;
height: 10rpx;
margin-left: 24rpx;
}
.list_footer {
padding: 32rpx 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #ec7c00;
.see_more {
display: flex;
align-items: center;
.see_more_icon {
width: 22rpx;
height: 22rpx;
margin-left: 10rpx;
}
}
}
.colorRed {
color: #d9001b;
}
.colorGreen {
color: #8fc320;
}
</style>