fks-yangshouda
4 months ago
11 changed files with 1264 additions and 422 deletions
Before Width: | Height: | Size: 969 B After Width: | Height: | Size: 954 B |
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 535 B |
After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1,206 @@ |
|||
<template> |
|||
<div ref="graphGraphchart" style="width: 100%; height: 80%"></div> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import { defineComponent, onMounted, ref } from 'vue'; |
|||
import * as echarts from 'echarts'; |
|||
|
|||
const data = [ |
|||
{ |
|||
date: '2023-12-01 0:00', |
|||
unit: 'V', |
|||
data: [ |
|||
{ |
|||
name: 'AC_002(暖通电表)', |
|||
value: '21', |
|||
}, |
|||
{ |
|||
name: 'AC_003(照明电表)', |
|||
value: '36', |
|||
}, |
|||
{ |
|||
name: 'AC_004(给排水电表)', |
|||
value: '5', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
date: '2023-12-02 0:00', |
|||
unit: 'V', |
|||
data: [ |
|||
{ |
|||
name: 'AC_002(暖通电表)', |
|||
value: '26', |
|||
}, |
|||
{ |
|||
name: 'AC_003(照明电表)', |
|||
value: '25', |
|||
}, |
|||
{ |
|||
name: 'AC_004(给排水电表)', |
|||
value: '47', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
date: '2023-12-03 0:00', |
|||
unit: 'V', |
|||
data: [ |
|||
{ |
|||
name: 'AC_002(暖通电表)', |
|||
value: '18', |
|||
}, |
|||
{ |
|||
name: 'AC_003(照明电表)', |
|||
value: '22', |
|||
}, |
|||
{ |
|||
name: 'AC_004(给排水电表)', |
|||
value: '26', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
date: '2023-12-04 0:00', |
|||
unit: 'V', |
|||
data: [ |
|||
{ |
|||
name: 'AC_002(暖通电表)', |
|||
value: '40', |
|||
}, |
|||
{ |
|||
name: 'AC_003(照明电表)', |
|||
value: '15', |
|||
}, |
|||
{ |
|||
name: 'AC_004(给排水电表)', |
|||
value: '12', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
date: '2023-12-05 0:00', |
|||
unit: 'V', |
|||
data: [ |
|||
{ |
|||
name: 'AC_002(暖通电表)', |
|||
value: '15', |
|||
}, |
|||
{ |
|||
name: 'AC_003(照明电表)', |
|||
value: '18', |
|||
}, |
|||
{ |
|||
name: 'AC_004(给排水电表)', |
|||
value: '15', |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
|
|||
export default defineComponent({ |
|||
name: 'GraphGraph', |
|||
setup() { |
|||
const graphGraphchart = ref(null); |
|||
|
|||
let chartInstance: echarts.ECharts | null = null; |
|||
onMounted(() => { |
|||
chartInstance = echarts.init(graphGraphchart.value); |
|||
var seriesList = []; |
|||
var date = []; |
|||
var legendList: string | any[] = []; |
|||
for (let i = 0; i < data.length; i++) { |
|||
date.push(data[i].date); |
|||
|
|||
for (let j = 0; j < data[i].data.length; j++) { |
|||
if (seriesList.length < j + 1) { |
|||
seriesList.push({ |
|||
name: data[i].data[j].name, |
|||
data: [data[i].data[j].value], |
|||
type: 'line', |
|||
smooth: true, |
|||
}); |
|||
} else { |
|||
seriesList[j].data.push(data[i].data[j].value); |
|||
} |
|||
if (legendList.length == 0 || legendList.length < j + 1) { |
|||
legendList.push(data[i].data[j].name); |
|||
} |
|||
} |
|||
} |
|||
const option = { |
|||
legend: { |
|||
data: legendList, |
|||
orient: 'horizontal', |
|||
bottom: 0, |
|||
left: 60, |
|||
}, |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
formatter: (params: any) => { |
|||
const date = params[0].name; |
|||
const values = params |
|||
.map((param: any) => { |
|||
const unit = data.find((d) => d.date === date)?.unit || ''; |
|||
return `<tr> |
|||
<td>${param.marker}${param.seriesName}</td> |
|||
<td style="text-align: right;">${param.value} ${unit}</td> |
|||
</tr>`; |
|||
}) |
|||
.join(''); |
|||
return `<div>${date}</div><table style="width: 100%;">${values}</table>`; |
|||
}, |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
data: date, |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
}, |
|||
// dataZoom: [ |
|||
// { |
|||
// height: 10, |
|||
// start: 0, |
|||
// end: 100, |
|||
// handleSize: '300%', // 设置滑块的大小 |
|||
// bottom: 15, |
|||
// }, |
|||
// ], |
|||
// toolbox: { |
|||
// show: true, |
|||
// feature: { |
|||
// mark: { show: true }, |
|||
// saveAsImage: { show: true }, |
|||
// }, |
|||
// }, |
|||
series: seriesList, |
|||
}; |
|||
|
|||
chartInstance = echarts.init(graphGraphchart.value); |
|||
chartInstance.setOption(option); |
|||
}); |
|||
|
|||
// 下载图表 |
|||
const downloadChart = () => { |
|||
if (chartInstance) { |
|||
const base64 = chartInstance.getDataURL({ |
|||
type: 'png', |
|||
backgroundColor: '#fff', |
|||
}); |
|||
const link = document.createElement('a'); |
|||
link.href = base64; |
|||
link.download = 'chart.png'; |
|||
link.click(); |
|||
} |
|||
}; |
|||
|
|||
return { |
|||
graphGraphchart, |
|||
downloadChart, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
<style lang="less" scoped></style> |
@ -0,0 +1,88 @@ |
|||
<!-- eslint-disable vue/multi-word-component-names --> |
|||
<template> |
|||
<a-tabs v-model:activeKey="activeKey" style="height: 8%"> |
|||
<a-tab-pane key="1" tab="图表" /> |
|||
<a-tab-pane key="2" tab="分析" /> |
|||
</a-tabs> |
|||
<a-row type="flex" style="height: 92%"> |
|||
<a-col :span="4"> |
|||
<div style="padding: 0 20px; width: 100%; height: 100%"> |
|||
<tree ref="treeRef" /> |
|||
</div> |
|||
</a-col> |
|||
<a-col :span="20"> |
|||
<div style="width: 100%; height: 100%"> |
|||
<div class="ns-right-title"> |
|||
<span>统计数据</span> |
|||
<div class="button"> |
|||
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" /> |
|||
<ns-icon :name="iconName" size="18" style="margin-right: 10px" @click="change" /> |
|||
</div> |
|||
</div> |
|||
<div v-if="activeKey == '1'" style="height: 90%"> |
|||
<graph-graph ref="graphRef" v-if="isGraph" /> |
|||
<environment-table ref="tableRef" v-else /> |
|||
</div> |
|||
</div> |
|||
</a-col> |
|||
</a-row> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
import tree from './tree/index.vue'; |
|||
import graphGraph from './graphGraph/index.vue'; |
|||
import environmentTable from './table/index.vue'; |
|||
|
|||
const iconName = ref('biaoge'); |
|||
|
|||
const treeRef = ref(); |
|||
const graphRef = ref(); |
|||
const tableRef = ref(); |
|||
|
|||
let isGraph = ref(true); |
|||
const activeKey = ref('1'); |
|||
|
|||
defineOptions({ |
|||
name: 'EnvironmentMonitorIndex', // 与页面路由name一致缓存才可生效 |
|||
}); |
|||
|
|||
const downloadChart = () => { |
|||
if (activeKey.value == '1' && isGraph) { |
|||
if (graphRef.value) { |
|||
graphRef.value.downloadChart(); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
function change() { |
|||
isGraph.value = !isGraph.value; |
|||
if (iconName.value == 'biaoge') { |
|||
iconName.value = 'bingtu'; |
|||
} else { |
|||
iconName.value = 'biaoge'; |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.ns-right-title { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
user-select: text; |
|||
margin-bottom: 5px; |
|||
padding-bottom: 10px; |
|||
padding-top: 10px; |
|||
border-bottom: 1px solid #e9e9e9; |
|||
|
|||
> span { |
|||
padding-left: 10px; |
|||
line-height: 20px; |
|||
} |
|||
} |
|||
.button { |
|||
display: inline-block; |
|||
padding-right: 10px; |
|||
} |
|||
</style> |
@ -0,0 +1,166 @@ |
|||
<template> |
|||
<a-table :columns="columns" :data-source="data" bordered /> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import { defineComponent } from 'vue'; |
|||
import type { TableColumnType } from 'ant-design-vue'; |
|||
|
|||
const data = [ |
|||
{ |
|||
key: '1', |
|||
name: 'AC_002(暖通电表)', |
|||
position: 'A 相电压', |
|||
unit: 'V', |
|||
date: '2023-12-01', |
|||
'1:00': '3626', |
|||
}, |
|||
{ |
|||
key: '1', |
|||
name: 'AC_002(暖通电表)', |
|||
position: 'A 相电压', |
|||
unit: 'V', |
|||
date: '2023-12-01', |
|||
'1:00': '3626', |
|||
}, |
|||
{ |
|||
key: '2', |
|||
name: 'AC_003(照明电表)', |
|||
position: 'A 相电压', |
|||
unit: 'V', |
|||
date: '2023-12-01', |
|||
'1:00': '3626', |
|||
}, |
|||
{ |
|||
key: '2', |
|||
name: 'AC_003(照明电表)', |
|||
position: 'A 相电压', |
|||
unit: 'V', |
|||
date: '2023-12-01', |
|||
'1:00': '3626', |
|||
}, |
|||
{ |
|||
key: '3', |
|||
name: 'AC_004(给排水电表)', |
|||
position: 'A 相电压', |
|||
unit: 'V', |
|||
date: '2023-12-01', |
|||
'1:00': '3626', |
|||
}, |
|||
]; |
|||
|
|||
export default defineComponent({ |
|||
name: 'EnvironmentTable', |
|||
setup() { |
|||
const getRowSpan = (dataIndex: string, record, data, dependents: string[] = []) => { |
|||
let rowSpan = 1; |
|||
for (let i = data.indexOf(record) + 1; i < data.length; i++) { |
|||
let shouldMerge = true; |
|||
for (const dependent of dependents) { |
|||
if (data[i][dependent] !== record[dependent]) { |
|||
shouldMerge = false; |
|||
break; |
|||
} |
|||
} |
|||
if (shouldMerge && data[i][dataIndex] === record[dataIndex]) { |
|||
rowSpan++; |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
return rowSpan; |
|||
}; |
|||
|
|||
const columns: TableColumnType[] = [ |
|||
{ |
|||
title: '序号', |
|||
dataIndex: 'key', |
|||
customCell: (record, rowIndex) => { |
|||
const rowSpan = getRowSpan('name', record, data); |
|||
if (rowIndex != 0 && data[rowIndex - 1].key == record.key) { |
|||
return { |
|||
rowSpan: 0, |
|||
colSpan: 0, |
|||
}; |
|||
} |
|||
return { |
|||
rowSpan: rowSpan, |
|||
}; |
|||
}, |
|||
}, |
|||
{ |
|||
title: '设备名称', |
|||
dataIndex: 'name', |
|||
customCell: (record, rowIndex) => { |
|||
const rowSpan = getRowSpan('name', record, data); |
|||
if (rowIndex != 0 && data[rowIndex - 1].name == record.name) { |
|||
return { |
|||
rowSpan: 0, |
|||
colSpan: 0, |
|||
}; |
|||
} |
|||
return { |
|||
rowSpan: rowSpan, |
|||
}; |
|||
}, |
|||
}, |
|||
{ |
|||
title: '设备点位', |
|||
dataIndex: 'position', |
|||
customCell: (record, rowIndex) => { |
|||
const rowSpan = getRowSpan('position', record, data, ['name']); |
|||
if ( |
|||
rowIndex != 0 && |
|||
data[rowIndex - 1].name == record.name && |
|||
data[rowIndex - 1].position == record.position |
|||
) { |
|||
return { |
|||
rowSpan: 0, |
|||
colSpan: 0, |
|||
}; |
|||
} |
|||
return { |
|||
rowSpan: rowSpan, |
|||
}; |
|||
}, |
|||
}, |
|||
{ |
|||
title: '计量单位', |
|||
dataIndex: 'unit', |
|||
customCell: (record, rowIndex) => { |
|||
const rowSpan = getRowSpan('unit', record, data, ['name', 'position']); |
|||
if ( |
|||
rowIndex != 0 && |
|||
data[rowIndex - 1].name == record.name && |
|||
data[rowIndex - 1].position == record.position && |
|||
data[rowIndex - 1].unit == record.unit |
|||
) { |
|||
return { |
|||
rowSpan: 0, |
|||
colSpan: 0, |
|||
}; |
|||
} |
|||
return { |
|||
rowSpan: rowSpan, |
|||
}; |
|||
}, |
|||
}, |
|||
{ |
|||
title: '日期', |
|||
dataIndex: 'date', |
|||
}, |
|||
{ |
|||
title: '1:00', |
|||
dataIndex: '1:00', |
|||
}, |
|||
]; |
|||
|
|||
return { |
|||
data, |
|||
columns, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="less" scoped></style> |
@ -0,0 +1,330 @@ |
|||
<!-- eslint-disable vue/v-on-event-hyphenation --> |
|||
<template> |
|||
<div class="parent-container"> |
|||
<div class="ns-tree-title"> |
|||
<span>数据点位</span> |
|||
</div> |
|||
<!-- <a-tree-select |
|||
v-model:value="value" |
|||
style="width: 100%" |
|||
|
|||
:tree-line="treeLine && { showLeafIcon }" |
|||
:tree-data="treeData1" |
|||
> |
|||
</a-tree-select> --> |
|||
<a-select |
|||
ref="select" |
|||
v-model:value="selectedValue" |
|||
placeholder="请选择能耗类型" |
|||
style="width: 100%; margin-bottom: 10px" |
|||
:options="options1" /> |
|||
|
|||
<a-radio-group |
|||
v-model:value="mode" |
|||
@change="changeMode" |
|||
style="padding-bottom: 10px; width: 100%"> |
|||
<a-radio-button value="1" style="width: 50%; text-align: center">设备</a-radio-button> |
|||
<a-radio-button value="2" style="width: 50%; text-align: center">节点</a-radio-button> |
|||
</a-radio-group> |
|||
<a-input v-model:value="value" placeholder="请输入设备名称" v-if="mode == '1'" /> |
|||
<a-input v-model:value="value" placeholder="请输入节点名称" v-else /> |
|||
<a-tree |
|||
v-model:expandedKeys="expandedKeys" |
|||
v-model:selectedKeys="selectedKeys" |
|||
v-model:checkedKeys="checkedKeys" |
|||
checkable |
|||
:height="300" |
|||
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px" |
|||
:tree-data="treeData2" /> |
|||
|
|||
<div class="fixed-bottom"> |
|||
<a-divider /> |
|||
<a-select |
|||
v-model:value="frequencyValue" |
|||
placeholder="请选择采集频率" |
|||
style="width: 100%; margin-bottom: 10px" |
|||
:options="options2" /> |
|||
<a-range-picker |
|||
:value="hackValue || dateRange" |
|||
:disabled-date="disabledDate" |
|||
@change="onChange" |
|||
@openChange="onOpenChange" |
|||
@calendarChange="onCalendarChange" |
|||
style="width: 100%; margin-bottom: 10px" |
|||
:placeholder="['请选择日期', '请选择日期']" /> |
|||
<a-button type="primary" style="width: 100%; margin-bottom: 10px" @click="getSelect" |
|||
>查询</a-button |
|||
> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import type { TreeSelectProps, TreeProps, SelectProps } from 'ant-design-vue'; |
|||
import { defineComponent, ref, onMounted } from 'vue'; |
|||
import { Dayjs } from 'dayjs'; |
|||
|
|||
export default defineComponent({ |
|||
// eslint-disable-next-line vue/multi-word-component-names |
|||
name: 'Tree', |
|||
setup() { |
|||
// const treeLine = ref(true); |
|||
// const showLeafIcon = ref(false); |
|||
const value = ref<string>(); |
|||
|
|||
const treeData1 = ref<TreeSelectProps['treeData']>([ |
|||
{ |
|||
title: '3.电梯', |
|||
value: '3', |
|||
children: [ |
|||
{ |
|||
title: '301.扶梯', |
|||
value: '301', |
|||
}, |
|||
{ |
|||
title: '302.直梯', |
|||
value: '302', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
title: '4.冷热源', |
|||
value: '4', |
|||
children: [ |
|||
{ |
|||
title: '401.冷水机组', |
|||
value: '401', |
|||
}, |
|||
{ |
|||
title: '402.热泵机组', |
|||
value: '402', |
|||
}, |
|||
{ |
|||
title: '403.锅炉', |
|||
value: '403', |
|||
}, |
|||
{ |
|||
title: '404.水处理机组', |
|||
value: '404', |
|||
}, |
|||
], |
|||
}, |
|||
]); |
|||
|
|||
const expandedKeys = ref<string[]>(['0-0-0', '0-0-1']); |
|||
const selectedKeys = ref<string[]>(['0-0-0', '0-0-1']); |
|||
const checkedKeys = ref<string[]>(['0-0-0', '0-0-1']); |
|||
|
|||
const options1 = ref<SelectProps['options']>([]); |
|||
const options2 = ref<SelectProps['options']>([ |
|||
{ |
|||
value: '1', |
|||
label: '5分钟', |
|||
}, |
|||
{ |
|||
value: '2', |
|||
label: '10分钟', |
|||
}, |
|||
{ |
|||
value: '3', |
|||
label: '30分钟', |
|||
}, |
|||
{ |
|||
value: '4', |
|||
label: '1小时', |
|||
}, |
|||
]); |
|||
const mode = ref<String>('1'); |
|||
const selectedValue = ref<string | undefined>(); |
|||
const frequencyValue = ref<string | undefined>(); |
|||
const dateRange = ref<[Dayjs, Dayjs] | undefined>(); |
|||
|
|||
const getDianWeiList = () => { |
|||
console.log('getDianWeiList 被调用'); |
|||
options1.value = [ |
|||
{ value: '1', label: '用电量' }, |
|||
{ value: '2', label: '用水量' }, |
|||
{ value: '3', label: '碳排量' }, |
|||
{ value: '4', label: '标煤量' }, |
|||
]; |
|||
}; |
|||
|
|||
const getSelect = () => {}; |
|||
|
|||
const treeData2 = ref<TreeProps['treeData']>([]); |
|||
const changeMode = () => { |
|||
if (mode.value == '1') { |
|||
treeData2.value = [ |
|||
{ |
|||
title: 'AC_001(总电表)', |
|||
key: '101', |
|||
children: [ |
|||
{ |
|||
title: 'AC_002(暖通电表)', |
|||
key: '102', |
|||
}, |
|||
{ |
|||
title: 'AC_003(照明电表)', |
|||
key: '103', |
|||
}, |
|||
{ |
|||
title: 'AC_004(给排水电表)', |
|||
key: '104', |
|||
}, |
|||
{ |
|||
title: 'AC_005(通风电表)', |
|||
key: '105', |
|||
}, |
|||
{ |
|||
title: 'AC_006(电动门电表)', |
|||
key: '106', |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
} else { |
|||
treeData2.value = [ |
|||
{ |
|||
title: '功能分项', |
|||
key: '1', |
|||
children: [ |
|||
{ |
|||
title: '照明', |
|||
key: '2', |
|||
children: [ |
|||
{ |
|||
title: '站台照明', |
|||
key: '3', |
|||
}, |
|||
{ |
|||
title: '站厅照明', |
|||
key: '4', |
|||
}, |
|||
{ |
|||
title: '应急照明', |
|||
key: '5', |
|||
}, |
|||
{ |
|||
title: '广告照明', |
|||
key: '6', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
title: '暖通', |
|||
key: '7', |
|||
}, |
|||
{ |
|||
title: '排放', |
|||
key: '8', |
|||
}, |
|||
{ |
|||
title: '给排水', |
|||
key: '9', |
|||
}, |
|||
{ |
|||
title: '光伏', |
|||
key: '10', |
|||
}, |
|||
{ |
|||
title: '电梯', |
|||
key: '11', |
|||
}, |
|||
{ |
|||
title: '电动门', |
|||
key: '12', |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
} |
|||
}; |
|||
|
|||
type RangeValue = [Dayjs, Dayjs]; |
|||
const dates = ref<RangeValue>(); |
|||
const hackValue = ref<RangeValue>(); |
|||
|
|||
const disabledDate = (current: Dayjs) => { |
|||
if (!dates.value || (dates.value as any).length === 0) { |
|||
return false; |
|||
} |
|||
const tooLate = dates.value[0] && current.diff(dates.value[0], 'days') > 2; |
|||
const tooEarly = dates.value[1] && dates.value[1].diff(current, 'days') > 2; |
|||
return tooEarly || tooLate; |
|||
}; |
|||
|
|||
const onOpenChange = (open: boolean) => { |
|||
if (open) { |
|||
dates.value = [] as any; |
|||
hackValue.value = [] as any; |
|||
} else { |
|||
hackValue.value = undefined; |
|||
} |
|||
}; |
|||
|
|||
const onChange = (val: RangeValue) => { |
|||
dateRange.value = val; |
|||
}; |
|||
|
|||
const onCalendarChange = (val: RangeValue) => { |
|||
dates.value = val; |
|||
}; |
|||
onMounted(() => { |
|||
getDianWeiList(); |
|||
changeMode(); |
|||
}); |
|||
|
|||
// const dateFormat = 'YYYY-MM-DD'; |
|||
|
|||
return { |
|||
// treeLine, |
|||
// showLeafIcon, |
|||
value, |
|||
treeData1, |
|||
treeData2, |
|||
expandedKeys, |
|||
selectedKeys, |
|||
checkedKeys, |
|||
options1, |
|||
options2, |
|||
mode, |
|||
selectedValue, |
|||
frequencyValue, |
|||
dateRange, |
|||
getDianWeiList, |
|||
getSelect, |
|||
changeMode, |
|||
disabledDate, |
|||
onCalendarChange, |
|||
onOpenChange, |
|||
onChange, |
|||
hackValue, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.ns-tree-title { |
|||
user-select: text; |
|||
margin-bottom: 5px; |
|||
padding-bottom: 10px; |
|||
padding-top: 10px; |
|||
border-bottom: 1px solid #e9e9e9; |
|||
> span { |
|||
padding-left: 10px; |
|||
line-height: 20px; |
|||
} |
|||
} |
|||
.parent-container { |
|||
position: relative; |
|||
height: 100%; |
|||
} |
|||
|
|||
.fixed-bottom { |
|||
position: absolute; |
|||
bottom: 0; |
|||
width: 100%; |
|||
margin-bottom: 10px; |
|||
} |
|||
</style> |
Loading…
Reference in new issue