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.
716 lines
20 KiB
716 lines
20 KiB
<template>
|
|
<div ref="bottomRadarRef" id="bottomRadarChart"></div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onBeforeUnmount } from 'vue'
|
|
import { createChartResizeHandler, applyResponsiveStyles } from '@/utils/chartResize.js'
|
|
import * as echarts from 'echarts'
|
|
const bottomRadarRef = ref(null)
|
|
let bottomRadarChart = null
|
|
let resizeHandler = null
|
|
function initEmotionalBottomRadar(KlineData, barAndLineData) {
|
|
// 如果已存在图表实例,先销毁
|
|
if (bottomRadarChart) {
|
|
bottomRadarChart.dispose()
|
|
bottomRadarChart = null
|
|
}
|
|
|
|
let bottomRadarChartDom = document.getElementById('bottomRadarChart')
|
|
bottomRadarChart = echarts.init(bottomRadarChartDom)
|
|
|
|
// 日期-作为x轴
|
|
let dateArray = barAndLineData.map(subArray => subArray[0])
|
|
// k线数据格式:['2025/04/24', 250.5, 259.51, 249.2, 259.54, 274.899, 0.685, 258.354]
|
|
// 原始数据:索引1=开盘价, 索引2=收盘价, 索引3=最低价, 索引4=最高价
|
|
// ECharts candlestick需要:[开盘, 收盘, 最低, 最高]
|
|
let kLineDataArray = KlineData.map(subArray => [
|
|
subArray[1], // 开盘价
|
|
subArray[2], // 收盘价
|
|
subArray[3], // 最低价
|
|
subArray[4] // 最高价
|
|
])
|
|
|
|
// 计算K线数据的最小值,用于设置y轴起始值
|
|
let allKlineValues = []
|
|
kLineDataArray.forEach(item => {
|
|
if (Array.isArray(item) && item.length >= 4) {
|
|
// K线数据格式:[开盘价, 收盘价, 最低价, 最高价]
|
|
allKlineValues.push(item[0], item[1], item[2], item[3])
|
|
}
|
|
})
|
|
|
|
// 找到最小值和最大值
|
|
let validValues = allKlineValues.filter(val => typeof val === 'number' && !isNaN(val))
|
|
let minValue = Math.min(...validValues)
|
|
let maxValue = Math.max(...validValues)
|
|
|
|
// 最小值向下取整,最大值向上取整
|
|
let yAxisMin = Math.floor(minValue)
|
|
let yAxisMax = Math.ceil(maxValue)
|
|
// 红线,取第二个值
|
|
let redLineDataArray = barAndLineData.map(subArray => subArray[1])
|
|
// 色块数据格式化
|
|
let barTotalDataArray = barAndLineData.map(subArray => subArray.slice(2, 6))
|
|
// 删掉
|
|
// barTotalDataArray[0] = [0, 0, 0, 0]
|
|
// barTotalDataArray[8] = [1, 1, 1, 1]
|
|
// barTotalDataArray[9] = [0, 0, 1, 1]
|
|
// barTotalDataArray[13] = [1, 0, 1, 0]
|
|
// barTotalDataArray[16] = [0, 0, 1, 0]
|
|
// 黄色块、黄色加仓资金、紫色柱子、蓝色柱子
|
|
let yellowBlockDataArray = []
|
|
let yellowLineDataArray = []
|
|
let purpleLineDataArray = []
|
|
let blueLineDataArray = []
|
|
let transparentFillingDataArray = []
|
|
// 黄色块:为1 0-4显示柱体
|
|
// 黄色加仓资金文字:为1 在4的位置展示文字
|
|
// 紫色柱子:为1 1-80显示柱体
|
|
// 蓝色柱子:为1 0-40显示柱体
|
|
// 因数据要互相叠加展示,所以需要数据处理。base适用于 ECharts 4.x 及以上版本
|
|
barTotalDataArray.forEach((item) => {
|
|
if (item[0]) {
|
|
yellowBlockDataArray.push(4)
|
|
if (item[3]) {
|
|
// 40-4
|
|
blueLineDataArray.push(36)
|
|
if (item[2]) {
|
|
// 80-40
|
|
purpleLineDataArray.push(40)
|
|
transparentFillingDataArray.push(0)
|
|
} else {
|
|
purpleLineDataArray.push(0)
|
|
transparentFillingDataArray.push(0)
|
|
}
|
|
} else {
|
|
blueLineDataArray.push(0)
|
|
if (item[2]) {
|
|
// 80-4
|
|
purpleLineDataArray.push(76)
|
|
transparentFillingDataArray.push(0)
|
|
} else {
|
|
purpleLineDataArray.push(0)
|
|
transparentFillingDataArray.push(0)
|
|
}
|
|
}
|
|
} else if (!item[0]) {
|
|
yellowBlockDataArray.push(0)
|
|
if (item[3]) {
|
|
blueLineDataArray.push(40)
|
|
if (item[2]) {
|
|
// 80-40
|
|
purpleLineDataArray.push(40)
|
|
transparentFillingDataArray.push(0)
|
|
} else {
|
|
purpleLineDataArray.push(0)
|
|
transparentFillingDataArray.push(0)
|
|
}
|
|
} else {
|
|
blueLineDataArray.push(0)
|
|
if (item[2]) {
|
|
// 80-1,base为1
|
|
purpleLineDataArray.push(79)
|
|
transparentFillingDataArray.push(1)
|
|
} else {
|
|
purpleLineDataArray.push(0)
|
|
transparentFillingDataArray.push(0)
|
|
}
|
|
}
|
|
}
|
|
// 加仓资金
|
|
if (item[1]) {
|
|
yellowLineDataArray.push(1)
|
|
} else if (!item[1]) {
|
|
yellowLineDataArray.push(0)
|
|
}
|
|
})
|
|
|
|
// 配置图表选项,很多操作和展示已限制,如果需要需放开
|
|
let option = {
|
|
// backgroundColor: '#000046', // 设置整个图表的背景色
|
|
tooltip: {
|
|
show: true, // 启用tooltip显示
|
|
trigger: 'axis',
|
|
triggerOn: 'mousemove',
|
|
confine: true,
|
|
axisPointer: {
|
|
type: 'cross',
|
|
crossStyle: {
|
|
color: '#fff',
|
|
width: 1,
|
|
type: 'solid'
|
|
},
|
|
lineStyle: {
|
|
color: '#fff',
|
|
width: 1,
|
|
type: 'solid'
|
|
},
|
|
label: {
|
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
color: '#fff',
|
|
borderColor: '#fff',
|
|
borderWidth: 1
|
|
}
|
|
},
|
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
borderColor: '#fff',
|
|
borderWidth: 1,
|
|
padding: 10,
|
|
textStyle: {
|
|
color: '#fff',
|
|
fontSize: 12
|
|
},
|
|
formatter: function (params) {
|
|
if (!params || params.length === 0) return ''
|
|
|
|
// 检查是否有第二个或第三个网格的数据,如果有则不显示tooltip
|
|
let hasSecondOrThirdGrid = params.some(param => {
|
|
return (param.seriesName === '红线' && param.axisIndex === 1) ||
|
|
(param.axisIndex === 2) ||
|
|
(param.seriesName !== 'K线' && param.seriesName !== '基础base')
|
|
})
|
|
|
|
// 如果鼠标悬浮在第二个或第三个网格上,不显示tooltip
|
|
if (hasSecondOrThirdGrid && !params.some(param => param.seriesType === 'candlestick')) {
|
|
return ''
|
|
}
|
|
|
|
let result = `<div style="font-weight: bold; color: #fff; margin-bottom: 8px;">${params[0].name}</div>`
|
|
|
|
params.forEach(param => {
|
|
let value = param.value
|
|
let color = param.color
|
|
|
|
if (param.seriesType === 'candlestick') {
|
|
// ECharts candlestick的value格式:[开盘, 收盘, 最低, 最高]
|
|
let candlestickData = param.value
|
|
|
|
// 确保数据有效性
|
|
if (!Array.isArray(candlestickData) || candlestickData.length < 4) {
|
|
return ''
|
|
}
|
|
|
|
let openPrice = candlestickData[1] // 开盘价
|
|
let closePrice = candlestickData[2] // 收盘价
|
|
let lowPrice = candlestickData[3] // 最低价
|
|
let highPrice = candlestickData[4] // 最高价
|
|
|
|
// 确保所有价格都是有效数字
|
|
if (typeof openPrice !== 'number' || typeof closePrice !== 'number' ||
|
|
typeof lowPrice !== 'number' || typeof highPrice !== 'number') {
|
|
return ''
|
|
}
|
|
|
|
let priceChange = closePrice - openPrice
|
|
let changePercent = ((priceChange / openPrice) * 100).toFixed(2)
|
|
let changeColor = priceChange >= 0 ? '#14b143' : '#ef232a' // 互换颜色:上涨红色,下跌绿色
|
|
|
|
result += `<div style="margin-bottom: 6px;">`
|
|
result += `<div style="color: #fff; font-weight: bold;">${param.seriesName}</div>`
|
|
result += `<div style="color: #fff;">开盘: ${openPrice.toFixed(1)}</div>`
|
|
result += `<div style="color: #fff;">收盘: ${closePrice.toFixed(1)}</div>`
|
|
result += `<div style="color: #fff;">最低: ${lowPrice.toFixed(1)}</div>`
|
|
result += `<div style="color: #fff;">最高: ${highPrice.toFixed(1)}</div>`
|
|
result += `<div style="color: ${changeColor};">涨跌: ${priceChange >= 0 ? '+' : ''}${priceChange.toFixed(2)} (${changePercent}%)</div>`
|
|
result += `</div>`
|
|
} else if (param.seriesName === '红线') {
|
|
result += `<div style="color: #ef232a; margin-bottom: 4px;">${param.seriesName}: ${value}</div>`
|
|
} else if (param.seriesName !== '基础base' && value > 0) {
|
|
result += `<div style="color: ${color}; margin-bottom: 4px;">${param.seriesName}: ${value}</div>`
|
|
}
|
|
})
|
|
return result
|
|
}
|
|
},
|
|
legend: {
|
|
// data: ['K线', '红线', '色块'], 不要展示图例
|
|
type: 'scroll',
|
|
pageButtonItemGap: 2,
|
|
pageButtonPosition: 'end',
|
|
textStyle: {
|
|
color: '#666'
|
|
}
|
|
},
|
|
grid: [
|
|
{
|
|
left: '10%',
|
|
right: '3%',
|
|
top: '20px',
|
|
bottom: '50%',
|
|
height: '300px',
|
|
width: '85%'
|
|
// containLabel: true
|
|
},
|
|
{
|
|
left: '10%',
|
|
right: '3%',
|
|
top: '320px',
|
|
bottom: '25%',
|
|
height: '300px',
|
|
width: '85%'
|
|
|
|
// containLabel: true
|
|
},
|
|
{
|
|
left: '10%',
|
|
right: '3%',
|
|
top: '620px',
|
|
bottom: '50px',
|
|
height: '300px',
|
|
width: '85%'
|
|
|
|
// containLabel: true
|
|
}
|
|
],
|
|
xAxis: [
|
|
{
|
|
type: 'category',
|
|
data: dateArray,
|
|
gridIndex: 0,
|
|
boundaryGap: true, // 保持间距,不要离y轴太近,不然重叠了
|
|
axisLine: {
|
|
// show: false,
|
|
lineStyle: {
|
|
color: 'white', // x轴线颜色
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: false
|
|
},
|
|
axisLabel: {
|
|
show: false
|
|
},
|
|
splitLine: {
|
|
show: false // 不要x轴的分割线
|
|
},
|
|
axisPointer: {
|
|
link: {
|
|
xAxisIndex: 'all'
|
|
},
|
|
}
|
|
},
|
|
{
|
|
type: 'category',
|
|
data: dateArray,
|
|
gridIndex: 1,
|
|
boundaryGap: true,
|
|
axisLine: {
|
|
// show: false,
|
|
lineStyle: {
|
|
// color: '#008000'
|
|
color: 'white'
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: false
|
|
},
|
|
axisLabel: {
|
|
show: false
|
|
},
|
|
splitLine: {
|
|
show: false
|
|
},
|
|
axisPointer: {
|
|
link: {
|
|
xAxisIndex: 'all'
|
|
}
|
|
}
|
|
},
|
|
{
|
|
type: 'category',
|
|
data: dateArray,
|
|
gridIndex: 2,
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: 'white'
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: true, // 显示刻度线
|
|
alignWithLabel: true,
|
|
lineStyle: {
|
|
color: '#999', // 颜色
|
|
width: 1, // 宽度
|
|
type: 'solid' // 线样式(solid/dashed/dotted)
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: 'white',
|
|
interval: 'auto', // 自动计算显示间隔,只显示部分日期但覆盖所有范围
|
|
rotate: 0 // 取消倾斜角度
|
|
},
|
|
splitLine: {
|
|
show: false
|
|
},
|
|
axisPointer: {
|
|
link: {
|
|
xAxisIndex: 'all'
|
|
}
|
|
}
|
|
}
|
|
],
|
|
yAxis: [
|
|
{
|
|
type: 'value',
|
|
gridIndex: 0,
|
|
splitNumber: 4,
|
|
min: yAxisMin, // 设置y轴最小值为数据最小值向下取整
|
|
max: yAxisMax, // 设置y轴最大值为数据最大值向上取整
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: 'white' // y轴坐标轴颜色
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: true
|
|
},
|
|
axisLabel: {
|
|
width: 50, // 宽度限制
|
|
color: 'white',
|
|
formatter: function (value, index) {
|
|
return value.toFixed(2)
|
|
}
|
|
},
|
|
splitLine: {
|
|
show: false,
|
|
lineStyle: {
|
|
color: '#837b7b',
|
|
type: 'dotted' // 设置网格线类型 dotted:虚线 solid:实线
|
|
}
|
|
},
|
|
scale: true, // 不强制包含0,不然k线图底部空余太多
|
|
},
|
|
{
|
|
type: 'value',
|
|
gridIndex: 1,
|
|
splitNumber: 3,
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: 'white'
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: true
|
|
},
|
|
splitNumber: 5, // 刻度数量
|
|
axisLabel: {
|
|
width: 50, // 宽度限制
|
|
color: 'white',
|
|
formatter: function (value, index) {
|
|
// 如果没有刻度数量,其他方法获取不到y轴刻度总长
|
|
if (index === 0) {
|
|
return '0'
|
|
} else if (index === 5) {
|
|
return ''
|
|
}
|
|
return value
|
|
}
|
|
},
|
|
splitLine: {
|
|
show: false,
|
|
lineStyle: {
|
|
color: '#837b7b',
|
|
type: 'dotted'
|
|
}
|
|
},
|
|
},
|
|
{
|
|
type: 'value',
|
|
gridIndex: 2,
|
|
splitNumber: 2,
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: 'white'
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: true
|
|
},
|
|
splitNumber: 5, // 刻度数量
|
|
axisLabel: {
|
|
width: 50, // 宽度限制
|
|
color: 'white',
|
|
formatter: function (value, index) {
|
|
if (index === 5) {
|
|
return ''
|
|
}
|
|
return value
|
|
}
|
|
},
|
|
splitLine: {
|
|
show: false,
|
|
lineStyle: {
|
|
color: '#837b7b',
|
|
type: 'dotted' // 设置网格线类型 dotted:虚线 solid:实线
|
|
}
|
|
},
|
|
splitNumber: 5,
|
|
min: function (value) {
|
|
return 0 // 最小值
|
|
},
|
|
max: function (value) {
|
|
return value.max + 10 // 比最大值高10, 避免最高点和上一个图表x轴重合
|
|
}
|
|
}
|
|
],
|
|
dataZoom: [
|
|
{
|
|
type: 'slider',
|
|
xAxisIndex: [0, 1, 2],
|
|
start: 0,
|
|
end: 100,
|
|
show: true,
|
|
bottom: window.innerWidth > 768 ? 80 : 50,
|
|
height: 20,
|
|
borderColor: '#CFD6E3',
|
|
fillerColor: 'rgba(135, 175, 274, 0.2)',
|
|
handleStyle: {
|
|
color: '#CFD6E3'
|
|
},
|
|
textStyle: {
|
|
color: '#fff'
|
|
},
|
|
dataBackground: {
|
|
lineStyle: {
|
|
color: '#CFD6E3'
|
|
},
|
|
areaStyle: {
|
|
color: 'rgba(241,243,247,0.5)'
|
|
}
|
|
}
|
|
},
|
|
{
|
|
type: 'inside',
|
|
xAxisIndex: [0, 1, 2],
|
|
start: 0,
|
|
end: 100,
|
|
zoomOnMouseWheel: true,
|
|
moveOnMouseMove: true,
|
|
moveOnMouseWheel: false
|
|
}
|
|
],
|
|
series: [
|
|
{
|
|
name: 'K线',
|
|
type: 'candlestick',
|
|
data: kLineDataArray,
|
|
xAxisIndex: 0,
|
|
yAxisIndex: 0,
|
|
itemStyle: {
|
|
color: '#14b143', // 开盘价 > 收盘价时为绿色
|
|
color0: '#ef232a', // 开盘价 < 收盘价时为红色
|
|
borderColor: '#14b143',
|
|
borderColor0: '#ef232a',
|
|
normal: {
|
|
color: '#14b143', // 开盘价 > 收盘价时为绿色
|
|
color0: '#ef232a', // 开盘价 < 收盘价时为红色
|
|
borderColor: '#14b143',
|
|
borderColor0: '#ef232a',
|
|
opacity: function (params) {
|
|
// K线数据格式:[开,收,低,高] 收盘价 > 开盘价时为阳线,设置边框不透明、填充透明
|
|
return params.data[1] > params.data[0] ? 0 : 1
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: '红线',
|
|
type: 'line',
|
|
data: redLineDataArray,
|
|
xAxisIndex: 1,
|
|
yAxisIndex: 1,
|
|
symbol: 'none',
|
|
sampling: 'average',
|
|
itemStyle: {
|
|
normal: {
|
|
color: '#ef232a'
|
|
}
|
|
},
|
|
areaStyle: {
|
|
color: {
|
|
type: 'linear',
|
|
x: 0,
|
|
y: 0,
|
|
x2: 0,
|
|
y2: 1,
|
|
colorStops: [
|
|
{ offset: 0, color: 'rgba(33, 150, 243, 0.4)' },
|
|
{ offset: 1, color: 'rgba(33, 150, 243, 0)' }
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: '基础base',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
// barGap: '-100%', // 重叠
|
|
xAxisIndex: 2,
|
|
yAxisIndex: 2,
|
|
barCategoryGap: '0%',
|
|
itemStyle: {
|
|
normal: {
|
|
color: '#ffffff',
|
|
borderWidth: 0,
|
|
}
|
|
},
|
|
data: transparentFillingDataArray,
|
|
},
|
|
{
|
|
name: '黄色',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
// barGap: '-100%', // 重叠
|
|
xAxisIndex: 2,
|
|
yAxisIndex: 2,
|
|
barCategoryGap: '0%', // 类目间柱条间距为0
|
|
itemStyle: {
|
|
normal: {
|
|
color: 'rgba(255, 255, 0, 1)',
|
|
borderWidth: 0,
|
|
// 加仓资金的文字显示
|
|
label: {
|
|
show: (params) => {
|
|
return yellowLineDataArray[params.dataIndex] > 0
|
|
},
|
|
position: 'top',
|
|
textStyle: {
|
|
color: 'rgba(255, 255, 0, 1)'
|
|
},
|
|
formatter: (params) => {
|
|
return yellowLineDataArray[params.dataIndex] > 0 ? '加仓资金' : ''
|
|
}
|
|
}
|
|
}
|
|
},
|
|
data: yellowBlockDataArray,
|
|
},
|
|
{
|
|
name: '蓝色',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
xAxisIndex: 2,
|
|
yAxisIndex: 2,
|
|
barCategoryGap: '0%', // 类目间柱条间距为0
|
|
label: {
|
|
show: true,
|
|
position: 'inside'
|
|
},
|
|
itemStyle: {
|
|
normal: {
|
|
color: 'rgba(34, 196, 190, 1)',
|
|
borderWidth: 0
|
|
}
|
|
},
|
|
data: blueLineDataArray
|
|
},
|
|
{
|
|
name: '紫色',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
xAxisIndex: 2,
|
|
yAxisIndex: 2,
|
|
barCategoryGap: '0%', // 类目间柱条间距为0
|
|
label: {
|
|
show: true,
|
|
position: 'inside'
|
|
},
|
|
itemStyle: {
|
|
normal: {
|
|
color: 'rgba(191, 87, 222, 1)',
|
|
borderWidth: 0
|
|
}
|
|
},
|
|
data: purpleLineDataArray
|
|
},
|
|
]
|
|
}
|
|
|
|
// 使用配置项显示图表
|
|
bottomRadarChart.setOption(option)
|
|
|
|
// 应用响应式样式
|
|
if (bottomRadarRef.value) {
|
|
applyResponsiveStyles(bottomRadarRef.value);
|
|
}
|
|
|
|
// 创建响应式处理器
|
|
if (resizeHandler) {
|
|
resizeHandler.cleanup();
|
|
}
|
|
|
|
resizeHandler = createChartResizeHandler({
|
|
chart: bottomRadarChart,
|
|
container: bottomRadarRef.value,
|
|
option: option,
|
|
beforeResize: adjustGridHeight,
|
|
name: '情绪探底雷达图表'
|
|
});
|
|
|
|
// 立即触发一次resize以确保初始布局正确
|
|
setTimeout(() => {
|
|
if (resizeHandler) {
|
|
resizeHandler.triggerResize();
|
|
}
|
|
}, 100);
|
|
function adjustGridHeight() {
|
|
if (window.innerWidth <= 768) {
|
|
option.grid[0].height = '150px'
|
|
option.grid[1].height = '150px'
|
|
option.grid[2].height = '150px'
|
|
option.grid[0].left = '15%'
|
|
option.grid[1].left = '15%'
|
|
option.grid[2].left = '15%'
|
|
option.grid[1].top = '170px'
|
|
option.grid[2].top = '320px'
|
|
option.grid[0].width = '80%'
|
|
option.grid[1].width = '80%'
|
|
option.grid[2].width = '80%'
|
|
}
|
|
bottomRadarChart.setOption(option)
|
|
}
|
|
|
|
// 初始化时调整高度
|
|
adjustGridHeight()
|
|
}
|
|
|
|
// 暴露给父级
|
|
defineExpose({
|
|
initEmotionalBottomRadar
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
// 清理响应式处理器
|
|
if (resizeHandler) {
|
|
resizeHandler.cleanup();
|
|
resizeHandler = null;
|
|
}
|
|
|
|
// 组件卸载时销毁图表
|
|
if (bottomRadarChart) {
|
|
bottomRadarChart.dispose();
|
|
bottomRadarChart = null;
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style>
|
|
#bottomRadarChart {
|
|
width: 100%;
|
|
height: 1040px;
|
|
box-sizing: border-box;
|
|
overflow: hidden;
|
|
margin: 0px auto !important;
|
|
padding: 0;
|
|
}
|
|
|
|
/* 手机端适配样式 */
|
|
@media only screen and (max-width: 768px) {
|
|
#bottomRadarChart {
|
|
width: 90% !important;
|
|
height: 560px;
|
|
padding: 0;
|
|
}
|
|
}
|
|
</style>
|