feat: 增加月线周线蜡烛图
This commit is contained in:
@@ -135,6 +135,36 @@ public class StockController extends SimpleControllerSupport<Stock, Void, StockD
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
|
@GetMapping("weekly/{id}")
|
||||||
|
public GlobalResponse<Map<String, Object>> weeklyCharts(@PathVariable("id") Long id) {
|
||||||
|
var data = stockService.findWeeklyRecent(id, 50);
|
||||||
|
var xList = new ArrayList<String>();
|
||||||
|
var yList = new ArrayList<List<Double>>();
|
||||||
|
for (var weekly : data) {
|
||||||
|
xList.add(weekly.tradeDate().toString());
|
||||||
|
yList.add(List.of(weekly.open(), weekly.close(), weekly.low(), weekly.high()));
|
||||||
|
}
|
||||||
|
return GlobalResponse.responseMapData(Map.of(
|
||||||
|
"xList", xList, "yList", yList
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
|
@GetMapping("monthly/{id}")
|
||||||
|
public GlobalResponse<Map<String, Object>> monthlyCharts(@PathVariable("id") Long id) {
|
||||||
|
var data = stockService.findMonthlyRecent(id, 24);
|
||||||
|
var xList = new ArrayList<String>();
|
||||||
|
var yList = new ArrayList<List<Double>>();
|
||||||
|
for (var monthly : data) {
|
||||||
|
xList.add(monthly.tradeDate().toString());
|
||||||
|
yList.add(List.of(monthly.open(), monthly.close(), monthly.low(), monthly.high()));
|
||||||
|
}
|
||||||
|
return GlobalResponse.responseMapData(Map.of(
|
||||||
|
"xList", xList, "yList", yList
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<Void, Stock> saveItemMapper() {
|
protected Function<Void, Stock> saveItemMapper() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {AlertComponent, attachmentAdpator, makeTranslator, render, type Schema, ToastComponent} from 'amis'
|
import {AlertComponent, type Api, attachmentAdpator, makeTranslator, render, type Schema, ToastComponent} from 'amis'
|
||||||
import 'amis/lib/themes/antd.css'
|
import 'amis/lib/themes/antd.css'
|
||||||
import 'amis/lib/helper.css'
|
import 'amis/lib/helper.css'
|
||||||
import 'amis/sdk/iconfont.css'
|
import 'amis/sdk/iconfont.css'
|
||||||
@@ -561,6 +561,139 @@ const financePropertyLabel = (idField: string, label: string, type: FinanceType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const candleChart = (title: string, subtitle: string, api: Api): Schema => {
|
||||||
|
return {
|
||||||
|
type: 'chart',
|
||||||
|
height: 500,
|
||||||
|
api: api,
|
||||||
|
config: {
|
||||||
|
title: {
|
||||||
|
text: title,
|
||||||
|
subtext: subtitle,
|
||||||
|
},
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
animation: true,
|
||||||
|
animationDuration: 1000,
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
},
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
||||||
|
borderColor: '#333',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
padding: 12,
|
||||||
|
formatter: function (params: any) {
|
||||||
|
const param = params[0]
|
||||||
|
const open = toNumber(param.data[1]).toFixed(2)
|
||||||
|
const close = toNumber(param.data[2]).toFixed(2)
|
||||||
|
const lowest = toNumber(param.data[3]).toFixed(2)
|
||||||
|
const highest = toNumber(param.data[4]).toFixed(2)
|
||||||
|
|
||||||
|
return `<div class="text-center font-bold mb-2">${param.name}</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<span>开盘:</span>
|
||||||
|
<span class="font-bold ml-4">${open}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<span>收盘:</span>
|
||||||
|
<span class="font-bold ml-4">${close}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<span>最低:</span>
|
||||||
|
<span class="font-bold ml-4">${lowest}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<span>最高:</span>
|
||||||
|
<span class="font-bold ml-4">${highest}</span>
|
||||||
|
</div>`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '2%',
|
||||||
|
right: '2%',
|
||||||
|
top: '15%',
|
||||||
|
bottom: '15%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
data: '${xList || []}',
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#e0e0e0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
scale: true,
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#e0e0e0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
formatter: function (value: number) {
|
||||||
|
return value.toFixed(2)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
type: 'dashed',
|
||||||
|
color: '#f0f0f0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
start: 0,
|
||||||
|
end: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
show: true,
|
||||||
|
type: 'slider',
|
||||||
|
top: '90%',
|
||||||
|
start: 0,
|
||||||
|
end: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'candlestick',
|
||||||
|
data: '${yList || []}',
|
||||||
|
itemStyle: {
|
||||||
|
color: '#eb5454',
|
||||||
|
color0: '#4aaa93',
|
||||||
|
borderColor: '#eb5454',
|
||||||
|
borderColor0: '#4aaa93',
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function stockListColumns(idField: string = 'id', extraColumns: Array<ColumnSchema> = []) {
|
export function stockListColumns(idField: string = 'id', extraColumns: Array<ColumnSchema> = []) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -803,137 +936,21 @@ export function stockListColumns(idField: string = 'id', extraColumns: Array<Col
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
candleChart(
|
||||||
type: 'chart',
|
'100日线数据',
|
||||||
title: '100日线数据',
|
'后复权数据',
|
||||||
height: 500,
|
`get:${commonInfo.baseUrl}/stock/daily/\${${idField}}`,
|
||||||
api: `get:${commonInfo.baseUrl}/stock/daily/\${${idField}}`,
|
),
|
||||||
config: {
|
candleChart(
|
||||||
title: {
|
'50周线数据',
|
||||||
text: '100日线数据',
|
'后复权数据',
|
||||||
subtext: '后复权数据',
|
`get:${commonInfo.baseUrl}/stock/weekly/\${${idField}}`,
|
||||||
},
|
),
|
||||||
backgroundColor: '#fff',
|
candleChart(
|
||||||
animation: true,
|
'24月线数据',
|
||||||
animationDuration: 1000,
|
'后复权数据',
|
||||||
tooltip: {
|
`get:${commonInfo.baseUrl}/stock/monthly/\${${idField}}`,
|
||||||
trigger: 'axis',
|
),
|
||||||
axisPointer: {
|
|
||||||
type: 'cross',
|
|
||||||
},
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
||||||
borderColor: '#333',
|
|
||||||
borderWidth: 1,
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: 12,
|
|
||||||
},
|
|
||||||
padding: 12,
|
|
||||||
formatter: function (params: any) {
|
|
||||||
const param = params[0]
|
|
||||||
const open = toNumber(param.data[1]).toFixed(2)
|
|
||||||
const close = toNumber(param.data[2]).toFixed(2)
|
|
||||||
const lowest = toNumber(param.data[3]).toFixed(2)
|
|
||||||
const highest = toNumber(param.data[4]).toFixed(2)
|
|
||||||
|
|
||||||
return `<div class="text-center font-bold mb-2">${param.name}</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<span>开盘:</span>
|
|
||||||
<span class="font-bold ml-4">${open}</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<span>收盘:</span>
|
|
||||||
<span class="font-bold ml-4">${close}</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<span>最低:</span>
|
|
||||||
<span class="font-bold ml-4">${lowest}</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<span>最高:</span>
|
|
||||||
<span class="font-bold ml-4">${highest}</span>
|
|
||||||
</div>`
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '2%',
|
|
||||||
right: '2%',
|
|
||||||
top: '15%',
|
|
||||||
bottom: '15%',
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
data: '${xList || []}',
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#e0e0e0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
color: '#666',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
scale: true,
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#e0e0e0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
color: '#666',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
formatter: function (value: number) {
|
|
||||||
return value.toFixed(2)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
type: 'dashed',
|
|
||||||
color: '#f0f0f0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
type: 'inside',
|
|
||||||
start: 0,
|
|
||||||
end: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
show: true,
|
|
||||||
type: 'slider',
|
|
||||||
top: '90%',
|
|
||||||
start: 0,
|
|
||||||
end: 100,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'candlestick',
|
|
||||||
data: '${yList || []}',
|
|
||||||
itemStyle: {
|
|
||||||
color: '#eb5454',
|
|
||||||
color0: '#4aaa93',
|
|
||||||
borderColor: '#eb5454',
|
|
||||||
borderColor0: '#4aaa93',
|
|
||||||
borderWidth: 1,
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user