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.
663 lines
20 KiB
663 lines
20 KiB
<template>
|
|
<div class="flex flex-row overflow-auto position-relative" style="height: calc(100vh - 125px)">
|
|
<div class="flex-1 h-full position-relative">
|
|
<OpenLayerMap
|
|
ref="mapRef"
|
|
class="map-container"
|
|
:showTrajectories="true"
|
|
:showDrawFences="false"
|
|
:markers="filterMarkers"
|
|
:fences="fences"
|
|
@time-range-change="timeRangeChange"
|
|
@on-click-marker="onClickMarker"
|
|
/>
|
|
<TopPanel
|
|
v-model:search="search"
|
|
v-model:selectStatus="selectStatus"
|
|
:handDetectorCount="handDetectorCount"
|
|
:onlineCount="onlineCount"
|
|
/>
|
|
</div>
|
|
<div class="markerList">
|
|
<div style="height: 100%">
|
|
<!-- <RecycleScroller
|
|
ref="scrollbarRef"
|
|
style="height: 100%"
|
|
:items="filterMarkers"
|
|
:item-size="48"
|
|
key-field="id"
|
|
v-slot="{ item }"
|
|
@scroll="onScroll"
|
|
>
|
|
<div class="marker-item" :data-id="item.id">
|
|
<div class="flex-1 text-left font-400 text-13px"> {{ item.name }}</div>
|
|
<div class="text-gray-500 font-400 text-12px pr-1" :style="{ color: item.statusColor }">
|
|
{{ item.statusLabel }}
|
|
</div>
|
|
</div>
|
|
</RecycleScroller> -->
|
|
|
|
<DynamicScroller
|
|
ref="scrollbarRef"
|
|
class="scroller"
|
|
:items="filterMarkers"
|
|
:min-item-size="48"
|
|
key-field="id"
|
|
v-slot="{ item, active }"
|
|
style="height: 100%"
|
|
@scroll="onScroll"
|
|
>
|
|
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.expanded]">
|
|
<div class="marker-panel">
|
|
<div class="marker-item" :data-id="item.id" @click="togglePanel(item)">
|
|
<div class="flex-1 text-left font-400 text-13px"> {{ item.name }}</div>
|
|
<div
|
|
class="text-gray-500 font-400 text-12px pr-1"
|
|
:style="{ color: item.statusColor }"
|
|
>
|
|
{{ item.statusLabel }}
|
|
</div>
|
|
</div>
|
|
<div v-show="item.expanded" class="markerList-content">
|
|
<div><span>SN:</span>{{ item.sn }}</div>
|
|
<div><span>类型:</span>{{ item.gasChemical }}</div>
|
|
|
|
<div
|
|
><span>气体状态:</span
|
|
>{{ getLabelWithTypeValue('gasStatus', item.gasStatus) }}</div
|
|
>
|
|
<div
|
|
><span>围栏状态:</span
|
|
>{{ getLabelWithTypeValue('fenceStatus', item.fenceStatus) }}</div
|
|
>
|
|
<div
|
|
><span>电池状态:</span
|
|
>{{ getLabelWithTypeValue('batteryStatus', item.batteryStatus) }}</div
|
|
>
|
|
|
|
<div><span>电量:</span>{{ item.battery }}</div>
|
|
<div><span>数值:</span>{{ item.value }} {{ item.unit }}</div>
|
|
<div><span>时间:</span>{{ item.timeStr }}</div>
|
|
|
|
<div style="margin-top: 10px">
|
|
<el-button
|
|
plain
|
|
size="small"
|
|
v-if="item.latitude && item.longitude"
|
|
@click="setCenter(item)"
|
|
>定位</el-button
|
|
>
|
|
<el-button
|
|
v-hasPermi="['gas:hand-td:HistoricalSn']"
|
|
plain
|
|
size="small"
|
|
@click="onClickTrajectory(item)"
|
|
>轨迹</el-button
|
|
>
|
|
<el-button
|
|
v-hasPermi="['gas:hand-td:HistoricalSn']"
|
|
plain
|
|
size="small"
|
|
@click="onClickHistoricalCurve(item)"
|
|
>历史曲线</el-button
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</DynamicScrollerItem>
|
|
</DynamicScroller>
|
|
</div>
|
|
</div>
|
|
<!--marker列表 -->
|
|
<!--
|
|
<el-scrollbar height="100%" ref="scrollbarRef" @scroll="onScroll">
|
|
<el-collapse accordion v-model="activeId">
|
|
<el-collapse-item :name="item.id" v-for="item in filterMarkers2" :key="item.id">
|
|
<template #title>
|
|
<div class="flex flex-row w-100%">
|
|
<div class="flex-1 text-left font-500">
|
|
{{ item.name }}
|
|
</div>
|
|
<div class="text-gray-500 font-400 text-12px" :style="{ color: item.statusColor }">
|
|
{{ item.statusLabel }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<div class="markerList-content">
|
|
<div><span>SN:</span>{{ item.sn }}</div>
|
|
<div><span>类型:</span>{{ item.gasChemical }}</div>
|
|
|
|
<div
|
|
><span>气体状态:</span
|
|
>{{ getLabelWithTypeValue('gasStatus', item.gasStatus) }}</div
|
|
>
|
|
<div
|
|
><span>围栏状态:</span
|
|
>{{ getLabelWithTypeValue('fenceStatus', item.fenceStatus) }}</div
|
|
>
|
|
<div
|
|
><span>电池状态:</span
|
|
>{{ getLabelWithTypeValue('batteryStatus', item.batteryStatus) }}</div
|
|
>
|
|
|
|
<div><span>电量:</span>{{ item.battery }}</div>
|
|
<div><span>数值:</span>{{ item.value }} {{ item.unit }}</div>
|
|
<div><span>时间:</span>{{ item.timeStr }}</div>
|
|
|
|
<div style="margin-top: 10px">
|
|
<el-button
|
|
plain
|
|
size="small"
|
|
v-if="item.latitude && item.longitude"
|
|
@click="setCenter(item)"
|
|
>定位</el-button
|
|
>
|
|
<el-button
|
|
v-hasPermi="['gas:hand-td:HistoricalSn']"
|
|
plain
|
|
size="small"
|
|
@click="onClickTrajectory(item)"
|
|
>轨迹</el-button
|
|
>
|
|
<el-button
|
|
v-hasPermi="['gas:hand-td:HistoricalSn']"
|
|
plain
|
|
size="small"
|
|
@click="onClickHistoricalCurve(item)"
|
|
>历史曲线</el-button
|
|
>
|
|
</div>
|
|
</div>
|
|
</el-collapse-item>
|
|
</el-collapse>
|
|
</el-scrollbar>
|
|
-->
|
|
|
|
<el-popover
|
|
ref="popoverRef"
|
|
:virtual-ref="virtualRef"
|
|
trigger="click"
|
|
title="With title"
|
|
virtual-triggering
|
|
>
|
|
<span> Some content </span>
|
|
</el-popover>
|
|
<HistoricalCurve ref="historicalCurveRef" />
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
|
import { RecycleScroller, DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller'
|
|
import OpenLayerMap from './components/OpenLayerMap.vue'
|
|
import TopPanel from './components/TopPanel.vue'
|
|
import HistoricalCurve from './components/HistoricalCurve.vue'
|
|
|
|
import { getLastDetectorData } from '@/api/gas'
|
|
import type { HandDetectorData } from '@/api/gas/handdetector'
|
|
import { tdengineApi } from '@/api/gas/tdengine/index'
|
|
|
|
import {
|
|
getLabelWithTypeValue,
|
|
getHighestPriorityStatus,
|
|
getStatusLabel,
|
|
getStatusColor,
|
|
getStatusPriority
|
|
} from './components/utils/map.utils'
|
|
|
|
import { MarkerData, FenceData } from './components/types/map.types'
|
|
|
|
import { useHandDetectorStore } from '@/store/modules/handDetector'
|
|
import { ElMessage, ElScrollbar } from 'element-plus'
|
|
import dayjs from 'dayjs'
|
|
import { getDistance } from 'ol/sphere'
|
|
|
|
const componentsIsActive = ref(false)
|
|
|
|
const handDetectorStore = useHandDetectorStore() // 手持探测器 store
|
|
|
|
const getDataTimer = ref<NodeJS.Timeout | null>(null)
|
|
const markers = ref<MarkerData[]>([])
|
|
const fences = ref<FenceData[]>([])
|
|
|
|
const mapRef = ref<InstanceType<typeof OpenLayerMap>>()
|
|
const search = ref('')
|
|
const selectStatus = ref(['normal', 'offline', 'fence', 'alarm'])
|
|
watch(
|
|
() => search.value,
|
|
(newSearch, oldSearch) => {
|
|
if (newSearch !== oldSearch) {
|
|
mapRef.value?.fitToMarkers()
|
|
}
|
|
},
|
|
{ immediate: false }
|
|
)
|
|
|
|
// 手持设备数量
|
|
const handDetectorCount = computed(() => markers.value.length)
|
|
const onlineCount = computed(() => markers.value.filter((item) => item.onlineStatus === 1).length)
|
|
const filterMarkers = computed(() => {
|
|
var arr = markers.value
|
|
if (search.value) {
|
|
arr = markers.value.filter((item) => {
|
|
var isName = item?.name?.includes(search.value)
|
|
var isSn = item.sn?.includes(search.value)
|
|
var isGasChemical = item.gasChemical?.includes(search.value)
|
|
|
|
return isName || isSn || isGasChemical
|
|
})
|
|
}
|
|
if (selectStatus.value.length !== 0) {
|
|
arr = arr.filter((item) => {
|
|
if (!item.statusStr) {
|
|
return true
|
|
}
|
|
if (item.statusStr == 'gasStatus_2' || item.statusStr == 'gasStatus_1') {
|
|
return selectStatus.value.includes('alarm')
|
|
}
|
|
return selectStatus.value.includes(item.statusStr)
|
|
})
|
|
}
|
|
// console.log('markers.value', markers.value)
|
|
|
|
return arr
|
|
})
|
|
|
|
// const filterMarkers2 = computed(() => {
|
|
// var arr: MarkerData[] = []
|
|
// for (let i = 0; i < 20000; i++) {
|
|
// arr.push({
|
|
// id: i + 1,
|
|
// sn: '867989072728120',
|
|
// battery: 3786,
|
|
// value: 4,
|
|
// longitude: 118.498279,
|
|
// latitude: 38.9647966,
|
|
// time: 1762937859776,
|
|
// name: '侯荣刚',
|
|
// fenceIds: '',
|
|
// fenceType: 1,
|
|
// gasTypeId: 1,
|
|
// unit: 'ppm',
|
|
// gasChemical: 'CO',
|
|
// batteryAlarmValue: 20,
|
|
// accuracy: 1,
|
|
// alarmLevel: -1,
|
|
// maxAlarmLevel: null,
|
|
// firstValue: null,
|
|
// maxValue: null,
|
|
// gpsType: 0,
|
|
// gasStatus: 0,
|
|
// alarmId: 200,
|
|
// batteryStatus: 0,
|
|
// batteryStatusAlarmId: null,
|
|
// fenceStatus: 0,
|
|
// fenceAlarmId: null,
|
|
// onlineStatus: 0,
|
|
// enableStatus: 1,
|
|
// distance: null,
|
|
// maxDistance: null,
|
|
// tenantId: null,
|
|
// talarmStart: null,
|
|
// talarmEnd: null,
|
|
// coordinates: [118.498279, 38.9647966],
|
|
// timeStr: '2025-11-12 16:57:39',
|
|
// statusStr: 'offline',
|
|
// statusColor: '#909399',
|
|
// statusLabel: '离线',
|
|
// statusPriority: 7,
|
|
// expanded: false
|
|
// })
|
|
// }
|
|
// return arr
|
|
// })
|
|
const getMarkers = async () => {
|
|
console.log('getMarkers')
|
|
return await getLastDetectorData().then((res: HandDetectorData[]) => {
|
|
res = res.filter((i) => i.enableStatus === 1)
|
|
var res2 = res
|
|
.map((i) => {
|
|
// console.log([i.longitude, i.latitude])
|
|
let statusStr = getHighestPriorityStatus({
|
|
gasStatus: i.gasStatus, //气体报警状态
|
|
batteryStatus: i.batteryStatus, //电池报警状态
|
|
fenceStatus: i.fenceStatus, //电子围栏报警状态
|
|
onlineStatus: i.onlineStatus //在线状态
|
|
}) //状态字符串
|
|
return {
|
|
...i,
|
|
coordinates: [i.longitude || 0, i.latitude || 0] as [number, number],
|
|
|
|
timeStr: i.time ? dayjs(i.time).format('YYYY-MM-DD HH:mm:ss') : '',
|
|
|
|
statusStr: statusStr, //状态字符串
|
|
statusColor: getStatusColor(statusStr), //状态颜色
|
|
statusLabel: getStatusLabel(statusStr), //状态标签
|
|
statusPriority: getStatusPriority(statusStr), //状态优先级,
|
|
expanded: activeId.value === i.id
|
|
}
|
|
})
|
|
.sort((a, b) => a.statusPriority - b.statusPriority)
|
|
markers.value = res2
|
|
})
|
|
}
|
|
const getFences = async () => {
|
|
return await handDetectorStore.getAllFences().then((res) => {
|
|
// console.log('getFences', res)
|
|
let fencesData = res
|
|
.map((i) => {
|
|
return {
|
|
...i,
|
|
fenceRange: JSON.parse(i.fenceRange)
|
|
}
|
|
})
|
|
.filter((i) => i.status === 1)
|
|
fences.value = fencesData as unknown as FenceData[]
|
|
})
|
|
}
|
|
// 定位到手持设备
|
|
function setCenter(item: MarkerData) {
|
|
console.log('setCenter', item)
|
|
if (item.longitude && item.latitude) {
|
|
mapRef.value?.setCenter([item.longitude || 0, item.latitude || 0])
|
|
}
|
|
}
|
|
// 记录当前选中的手持设备,主要用于重新获取轨迹
|
|
let currentMarker: MarkerData | null = null
|
|
var trajectoryTimeRange = ref([dayjs().subtract(1, 'hour').valueOf(), dayjs().valueOf()])
|
|
// 时间范围改变
|
|
function timeRangeChange(range: { startTime: number; endTime: number }) {
|
|
console.log('timeRangeChange', range)
|
|
trajectoryTimeRange.value = [range.startTime, range.endTime]
|
|
if (currentMarker) {
|
|
showTrajectory(currentMarker)
|
|
}
|
|
}
|
|
// 显示手持设备轨迹
|
|
async function showTrajectory(item: MarkerData) {
|
|
console.log('showTrajectory', item)
|
|
try {
|
|
if (!item.sn) {
|
|
ElMessage.error('手持设备无效')
|
|
return
|
|
}
|
|
currentMarker = item
|
|
const data = await tdengineApi.getHistoricalSn({
|
|
sn: item.sn,
|
|
startTime: dayjs(trajectoryTimeRange.value[0]).format('YYYY-MM-DD HH:mm:ss'),
|
|
endTime: dayjs(trajectoryTimeRange.value[1]).format('YYYY-MM-DD HH:mm:ss')
|
|
|
|
// sn: '867989072729904'
|
|
})
|
|
if (!data || data.length === 0) {
|
|
ElMessage.error(
|
|
`${dayjs(trajectoryTimeRange.value[0]).format('YYYY-MM-DD HH:mm:ss')}至${dayjs(trajectoryTimeRange.value[1]).format('YYYY-MM-DD HH:mm:ss')}时段没有轨迹数据`
|
|
)
|
|
// return
|
|
}
|
|
// 过滤前
|
|
// console.log('过滤前', data.length)
|
|
// 过滤掉重复点位和无效点位
|
|
var newData = data.filter((item, index, arr) => {
|
|
if (!item.longitude || !item.latitude) {
|
|
return false
|
|
}
|
|
if (index === 0) {
|
|
return true
|
|
}
|
|
// 过滤掉前后点位一样的
|
|
return (
|
|
item.longitude !== arr[index - 1]?.longitude || item.latitude !== arr[index - 1]?.latitude
|
|
)
|
|
})
|
|
// 过滤后
|
|
// console.log('过滤后', newData.length)
|
|
|
|
item.data = newData
|
|
.filter((item, index, arr) => {
|
|
if (index === 0) {
|
|
return true
|
|
}
|
|
if (index == arr.length - 1) {
|
|
return true
|
|
}
|
|
|
|
// 过滤掉前后点位相差超过100m的
|
|
let before = arr[index - 1]
|
|
let after = arr[index + 1]
|
|
|
|
let before_after_distance = getDistance(
|
|
[after.longitude, after.latitude],
|
|
[before.longitude, before.latitude]
|
|
)
|
|
|
|
// 过滤小范围移动点位
|
|
if (before_after_distance < 6) {
|
|
console.log('过滤小范围移动点位', before_after_distance)
|
|
return false
|
|
}
|
|
|
|
let beforeDistance = getDistance(
|
|
[before.longitude, before.latitude],
|
|
[item.longitude, item.latitude]
|
|
)
|
|
|
|
let afterDistance = getDistance(
|
|
[after.longitude, after.latitude],
|
|
[item.longitude, item.latitude]
|
|
)
|
|
|
|
// 过滤掉前、后点位都超过40m的,且前和后点位小于20m的,
|
|
if (beforeDistance > 40 && afterDistance > 40 && before_after_distance < 20) {
|
|
console.log(
|
|
'过滤掉前和后点位相差小于20m的,且与前、后点位都超过40m的',
|
|
beforeDistance,
|
|
afterDistance,
|
|
before_after_distance
|
|
)
|
|
return false
|
|
}
|
|
|
|
// console.log('beforeDistance', afterDistance)
|
|
// console.log('前距离', beforeDistance,'后距离',afterDistance,'前后距离',before_after_distance)
|
|
|
|
return true
|
|
})
|
|
.map((j) => {
|
|
return {
|
|
...j,
|
|
lng: j.longitude,
|
|
lat: j.latitude,
|
|
time: dayjs(j.ts).format('YYYY-MM-DD HH:mm:ss'),
|
|
timeStr: dayjs(j.ts).format('YYYY-MM-DD HH:mm:ss')
|
|
}
|
|
})
|
|
console.log('item.data', item.data)
|
|
|
|
mapRef.value?.showTrajectory(trajectoryTimeRange.value[0], trajectoryTimeRange.value[1], [item])
|
|
} finally {
|
|
}
|
|
}
|
|
const historicalCurveRef = ref<InstanceType<typeof HistoricalCurve>>()
|
|
// 点击历史曲线
|
|
function onClickHistoricalCurve(item: MarkerData) {
|
|
// console.log('onClickHistoricalCurve', item)
|
|
historicalCurveRef.value?.openDrawer(toRaw(item))
|
|
}
|
|
|
|
// 点击轨迹
|
|
function onClickTrajectory(item: MarkerData) {
|
|
console.log('onClickTrajectory', item)
|
|
trajectoryTimeRange.value = [dayjs().subtract(1, 'hour').valueOf(), dayjs().valueOf()]
|
|
showTrajectory(item)
|
|
}
|
|
const scrollbarRef = ref()
|
|
const virtualRef = ref<HTMLDivElement>()
|
|
const activeId = ref<number>()
|
|
// 点击手持设备
|
|
function onClickMarker(markerItem: MarkerData) {
|
|
console.log('onClickMarker', markerItem)
|
|
|
|
var findIndex = markers.value.findIndex((item) => item.id === markerItem.id)
|
|
if (findIndex === -1) {
|
|
return
|
|
}
|
|
showPannel(markerItem, findIndex)
|
|
}
|
|
const scrollbarScrollTop = ref(0)
|
|
function onScroll(e) {
|
|
// console.log('onScroll', e)
|
|
scrollbarScrollTop.value = e.target.scrollTop
|
|
}
|
|
|
|
// 滚动到指定位置
|
|
const AnimationId = ref<number>()
|
|
function scrollTo(from: number, to: number, current: number) {
|
|
if (scrollbarScrollTop.value === to) {
|
|
return
|
|
}
|
|
const speed = (to - from) / 30
|
|
|
|
if (speed < 0) {
|
|
if (current <= to) {
|
|
return
|
|
}
|
|
} else if (speed > 0) {
|
|
if (current >= to) {
|
|
return
|
|
}
|
|
}
|
|
current = current + speed
|
|
console.log('scrollbarRef.value', scrollbarRef.value)
|
|
// DynamicScroller内部用的RecycleScroller组件,所以滚动到指定位置用RecycleScroller方法
|
|
scrollbarRef.value?.$refs?.scroller?.scrollToPosition(current)
|
|
AnimationId.value = requestAnimationFrame(() => {
|
|
scrollTo(from, to, current)
|
|
})
|
|
}
|
|
const showPannel = (item, index) => {
|
|
if (activeId.value && activeId.value !== item.id) {
|
|
let last = markers.value.find((lastItem) => lastItem.id === activeId.value)
|
|
if (last) {
|
|
last.expanded = false
|
|
}
|
|
}
|
|
item.expanded = true
|
|
activeId.value = item.id
|
|
|
|
let top = index * 48
|
|
// scrollbarRef.value?.scrollToItem(index)
|
|
|
|
// 取消之前的动画
|
|
cancelAnimationFrame(AnimationId.value as number)
|
|
scrollTo(scrollbarScrollTop.value, top, scrollbarScrollTop.value)
|
|
}
|
|
const togglePanel = (item) => {
|
|
if (activeId.value && activeId.value !== item.id) {
|
|
let last = markers.value.find((lastItem) => lastItem.id === activeId.value)
|
|
if (last) {
|
|
last.expanded = false
|
|
}
|
|
}
|
|
|
|
if (item.expanded) {
|
|
activeId.value = undefined
|
|
item.expanded = false
|
|
} else {
|
|
activeId.value = item.id
|
|
item.expanded = true
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
getMarkers()
|
|
|
|
getFences()
|
|
|
|
getDataTimer.value = setInterval(() => {
|
|
if (!componentsIsActive.value) {
|
|
return
|
|
}
|
|
getMarkers()
|
|
getFences()
|
|
}, 4000)
|
|
})
|
|
|
|
onActivated(() => {
|
|
componentsIsActive.value = true
|
|
})
|
|
onDeactivated(() => {
|
|
componentsIsActive.value = false
|
|
})
|
|
onUnmounted(() => {
|
|
clearInterval(getDataTimer.value as NodeJS.Timeout)
|
|
})
|
|
</script>
|
|
<style scoped lang="scss">
|
|
.map-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.markerList {
|
|
position: absolute;
|
|
top: 60px;
|
|
right: 10px;
|
|
bottom: 10px;
|
|
width: 240px;
|
|
border-radius: 8px;
|
|
|
|
// height: 100%;
|
|
overflow: hidden;
|
|
background-color: rgba(255, 255, 255, 0.8);
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
|
padding: 5px 0 10px 10px;
|
|
margin-left: 10px;
|
|
.marker-panel {
|
|
box-sizing: border-box;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
}
|
|
.marker-item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
height: 48px;
|
|
line-height: 48px;
|
|
|
|
font-family: var(--el-font-family);
|
|
}
|
|
.markerList-content {
|
|
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
|
padding: 10px;
|
|
font-size: 12px;
|
|
font-weight: 400;
|
|
|
|
span {
|
|
display: inline-block;
|
|
min-width: 70px;
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
<style>
|
|
.el-collapse-item__header {
|
|
background-color: transparent;
|
|
color: #444343;
|
|
/* background-color: rgba(0, 0, 0, 0.5); */
|
|
}
|
|
.el-collapse-item__wrap {
|
|
background-color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: rgba(0, 0, 0, 0.1) !important; /* 滑块颜色 */
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
|
|
/*
|
|
::-webkit-scrollbar-thumb {
|
|
border-radius: 6px;
|
|
background-color: #555;
|
|
} */
|
|
</style>
|
|
|