|
@@ -1,60 +1,50 @@
|
|
|
<template>
|
|
|
<div class="right-legend">
|
|
|
<template v-for="(item, index) in rightPanelStore.riskLevelList" :key="index">
|
|
|
- <div class="legend-item" >
|
|
|
+ <div class="legend-item">
|
|
|
<div class="icon-box icon-box-fill">
|
|
|
<img :src="item.img" />
|
|
|
</div>
|
|
|
<div class="text-box">{{ item.name }}</div>
|
|
|
- <div
|
|
|
- class="switch-box"
|
|
|
- :class="{ switchOpen: item.value }"
|
|
|
- @click="handleRiskLevel(item)"
|
|
|
- ></div>
|
|
|
+ <div class="switch-box" :class="{ switchOpen: item.value }" @click="handleRiskLevel(item)"></div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
- <div class="line-box"></div>
|
|
|
- <template v-for="(item, index) in rightPanelStore.deviceList" :key="index">
|
|
|
- <div class="legend-item" @click="isDistrictLevel && handleDeviceLevel(item)" :class="{ disabled: !isDistrictLevel }">
|
|
|
- <div class="icon-box">
|
|
|
- <img :src="item.img" />
|
|
|
- </div>
|
|
|
- <div class="text-box">{{ item.name }}</div>
|
|
|
- <div class="switch-box" :class="{ switchOpen: item.value }"></div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
+ <!-- 折叠 -->
|
|
|
+ <transition name="fade-slide">
|
|
|
+ <div v-show="!isTimePickerOpen">
|
|
|
+ <div class="line-box"></div>
|
|
|
+ <template v-for="(item, index) in rightPanelStore.deviceList" :key="index">
|
|
|
+ <div class="legend-item" @click="isDistrictLevel && handleDeviceLevel(item)" :class="{ disabled: !isDistrictLevel }">
|
|
|
+ <div class="icon-box">
|
|
|
+ <img :src="item.img" />
|
|
|
+ </div>
|
|
|
+ <div class="text-box">{{ item.name }}</div>
|
|
|
+ <div class="switch-box" :class="{ switchOpen: item.value }"></div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
|
|
|
- <div class="line-box"></div>
|
|
|
+ <div class="line-box"></div>
|
|
|
|
|
|
- <template v-for="(item, index) in rightPanelStore.institutionList" :key="index">
|
|
|
- <div class="legend-item" @click="isDistrictLevel && handleInstitutionLevel(item)" :class="{ disabled: !isDistrictLevel }">
|
|
|
- <div class="icon-box">
|
|
|
- <img :src="item.img" />
|
|
|
- </div>
|
|
|
- <div class="text-box">{{ item.name }}</div>
|
|
|
- <div class="switch-box" :class="{ switchOpen: item.value }"></div>
|
|
|
+ <template v-for="(item, index) in rightPanelStore.institutionList" :key="index">
|
|
|
+ <div class="legend-item" @click="isDistrictLevel && handleInstitutionLevel(item)" :class="{ disabled: !isDistrictLevel }">
|
|
|
+ <div class="icon-box">
|
|
|
+ <img :src="item.img" />
|
|
|
+ </div>
|
|
|
+ <div class="text-box">{{ item.name }}</div>
|
|
|
+ <div class="switch-box" :class="{ switchOpen: item.value }"></div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
- </template>
|
|
|
-
|
|
|
+ </transition>
|
|
|
<div class="line-box"></div>
|
|
|
|
|
|
- <div class="legend-item">
|
|
|
+ <div class="legend-item">
|
|
|
<div class="icon-box">
|
|
|
<img src="../../../../assets/img/Component 240(6).png" />
|
|
|
</div>
|
|
|
- <el-select
|
|
|
- v-model="bingliSelect"
|
|
|
- class="legend-select"
|
|
|
- placeholder="请选择病种"
|
|
|
- popper-class="custom-select"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="(item, index) in bingliArr"
|
|
|
- :key="index"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
- ></el-option>
|
|
|
+ <el-select v-model="bingliSelect" class="legend-select" placeholder="请选择病种" popper-class="custom-select">
|
|
|
+ <el-option v-for="(item, index) in bingliArr" :key="index" :label="item.label" :value="item.value"></el-option>
|
|
|
</el-select>
|
|
|
</div>
|
|
|
|
|
@@ -62,147 +52,175 @@
|
|
|
<div class="icon-box">
|
|
|
<img src="../../../../assets/img/Component 240(7).png" />
|
|
|
</div>
|
|
|
- <el-select
|
|
|
- class="legend-select"
|
|
|
- v-model="riskType"
|
|
|
- placeholder="请选择风险类型"
|
|
|
- popper-class="custom-select"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="(item, index) in riskTypeOptions"
|
|
|
- :key="index"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
- ></el-option>
|
|
|
+ <el-select class="legend-select" v-model="riskType" placeholder="请选择风险类型" popper-class="custom-select">
|
|
|
+ <el-option v-for="(item, index) in riskTypeOptions" :key="index" :label="item.label" :value="item.value"></el-option>
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="legend-item">
|
|
|
<div class="icon-box">
|
|
|
<img src="../../../../assets/img/Component 240(8).png" />
|
|
|
</div>
|
|
|
- <el-select
|
|
|
- v-model="timeSelect"
|
|
|
- class="legend-select"
|
|
|
- popper-class="custom-select"
|
|
|
- placeholder="请选择时间"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="(item, index) in timeArr"
|
|
|
- :key="index"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
- ></el-option
|
|
|
- ></el-select>
|
|
|
+ <el-tooltip :disabled="!commonStore.timeSelect.length" placement="bottom" effect="customized" :content="formatTimeRange(commonStore.timeSelect)" popper-class="tooltip-multiline">
|
|
|
+ <div class="date-picker-container" @click="handleDatePickerClick">
|
|
|
+ <el-date-picker
|
|
|
+ ref="datePickerRef"
|
|
|
+ v-model="commonStore.timeSelect"
|
|
|
+ type="datetimerange"
|
|
|
+ start-placeholder="开始时间"
|
|
|
+ end-placeholder="结束时间"
|
|
|
+ format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ date-format="YYYY/MM/DD ddd"
|
|
|
+ time-format="A hh:mm:ss"
|
|
|
+ teleported="false"
|
|
|
+ popper-class="date_picker_custom-class"
|
|
|
+ @visible-change="onDatePickerVisibleChange"
|
|
|
+ @change="onDateChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
</div>
|
|
|
<template v-if="commonStore.activeIndex == 1">
|
|
|
<div class="line-box"></div>
|
|
|
|
|
|
<div class="legend-item">
|
|
|
<div class="text-box">病例热点</div>
|
|
|
- <div
|
|
|
- class="switch-box"
|
|
|
- :class="{ switchOpen: bingliSwitch }"
|
|
|
- @click="handleBingli()"
|
|
|
- ></div>
|
|
|
+ <div class="switch-box" :class="{ switchOpen: bingliSwitch }" @click="handleBingli()"></div>
|
|
|
</div>
|
|
|
<div class="legend-item">
|
|
|
<div class="text-box">视频会商</div>
|
|
|
- <div
|
|
|
- class="switch-box"
|
|
|
- :class="{ switchOpen: videoSwitch }"
|
|
|
- @click="handleVideo()"
|
|
|
- ></div>
|
|
|
+ <div class="switch-box" :class="{ switchOpen: videoSwitch }" @click="handleVideo()"></div>
|
|
|
</div>
|
|
|
</template>
|
|
|
- <div class="legend-item">
|
|
|
+ <!-- <div class="legend-item">
|
|
|
<div class="text-box">时间轴</div>
|
|
|
- <div
|
|
|
- class="switch-box"
|
|
|
- :class="{ switchOpen: rightPanelStore.timerSwitchStatus }"
|
|
|
- @click="handleTimerSwitch"
|
|
|
- ></div>
|
|
|
- </div>
|
|
|
+ <div class="switch-box" :class="{ switchOpen: rightPanelStore.timerSwitchStatus }" @click="handleTimerSwitch"></div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup>
|
|
|
-import { ref,computed } from "vue";
|
|
|
-import { useCommonStore } from "@/store/common.js";
|
|
|
-import { useRightPanelStore } from "../../../../store/rightPanel";
|
|
|
-import {handleHeatMap} from "@/utils/map/baseMethod.js";
|
|
|
-import { riskTypeOptions } from "../../../../data/dict";
|
|
|
+import { ref, computed ,nextTick } from 'vue'
|
|
|
+import { useCommonStore } from '@/store/common.js'
|
|
|
+import { useRightPanelStore } from '../../../../store/rightPanel'
|
|
|
+import { handleHeatMap } from '@/utils/map/baseMethod.js'
|
|
|
+import { riskTypeOptions } from '../../../../data/dict'
|
|
|
+
|
|
|
+const commonStore = useCommonStore()
|
|
|
+const rightPanelStore = useRightPanelStore()
|
|
|
|
|
|
-const commonStore = useCommonStore();
|
|
|
-const rightPanelStore = useRightPanelStore();
|
|
|
+const districtList = ['全国', '全球', '上海市']
|
|
|
+const isDistrictLevel = computed(() => !districtList.includes(commonStore.areaLayerSwitchActive))
|
|
|
|
|
|
-const districtList = ["全国", "全球", "上海市"]
|
|
|
-const isDistrictLevel = computed(() =>
|
|
|
- !districtList.includes(commonStore.areaLayerSwitchActive)
|
|
|
-);
|
|
|
+const bingliSwitch = ref(false)
|
|
|
+const videoSwitch = ref(false)
|
|
|
|
|
|
-const bingliSwitch = ref(false);
|
|
|
-const videoSwitch = ref(false);
|
|
|
+const isTimePickerOpen = ref(false) // 控制是否折叠
|
|
|
+// 获取日期选择器组件实例
|
|
|
+const datePickerRef = ref(null)
|
|
|
+
|
|
|
+const onDatePickerVisibleChange = (visible) => {
|
|
|
+ if (visible) {
|
|
|
+ // 调整弹窗的位置
|
|
|
+ adjustPopperPosition()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const adjustPopperPosition = () => {
|
|
|
+ // 如果时间选择器弹窗被打开,动态调整其位置
|
|
|
+ const popper = document.querySelector('.el-picker-panel') // 获取弹窗
|
|
|
+ if (popper) {
|
|
|
+ const rect = datePickerRef.value.$el.getBoundingClientRect()
|
|
|
+ popper.style.top = `${rect.top + window.scrollY + 30}px` // 使其跟随
|
|
|
+ popper.style.left = `${rect.left + window.scrollX}px`
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 当用户点击整个日期选择器容器时,先折叠下面面板
|
|
|
+const handleDatePickerClick = () => {
|
|
|
+ // 如果面板还未折叠,则先折叠面板
|
|
|
+ if (!isTimePickerOpen.value) {
|
|
|
+ isTimePickerOpen.value = true
|
|
|
+ // 等待折叠动画结束(300ms),然后自动打开日期选择弹层
|
|
|
+ setTimeout(() => {
|
|
|
+ // 通过引用调用 datePicker 内部方法打开弹层
|
|
|
+ if (datePickerRef.value && datePickerRef.value.handleOpen) {
|
|
|
+ nextTick(() => {
|
|
|
+ datePickerRef.value.handleOpen()
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }, 300)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// // 日期选择完毕后,可执行其他逻辑,比如提示用户选择的时间范围
|
|
|
+const onDateChange = (val) => {
|
|
|
+ if (val && val.length === 2) {
|
|
|
+ const [start, end] = val
|
|
|
+ isTimePickerOpen.value =false
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
const handleBingli = () => {
|
|
|
- bingliSwitch.value = !bingliSwitch.value;
|
|
|
+ bingliSwitch.value = !bingliSwitch.value
|
|
|
handleHeatMap(bingliSwitch.value)
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
const handleTimerSwitch = () => {
|
|
|
- rightPanelStore.timerSwitchStatus = !rightPanelStore.timerSwitchStatus;
|
|
|
-};
|
|
|
+ rightPanelStore.timerSwitchStatus = !rightPanelStore.timerSwitchStatus
|
|
|
+}
|
|
|
|
|
|
const handleVideo = () => {
|
|
|
- videoSwitch.value = !videoSwitch.value;
|
|
|
-};
|
|
|
+ videoSwitch.value = !videoSwitch.value
|
|
|
+}
|
|
|
|
|
|
-const bingliSelect = ref("");
|
|
|
+const bingliSelect = ref('')
|
|
|
|
|
|
const bingliArr = ref([
|
|
|
{
|
|
|
- label: "流感",
|
|
|
- value: "流感",
|
|
|
+ label: '流感',
|
|
|
+ value: '流感'
|
|
|
},
|
|
|
{
|
|
|
- label: "肺炎",
|
|
|
- value: "肺炎",
|
|
|
+ label: '肺炎',
|
|
|
+ value: '肺炎'
|
|
|
},
|
|
|
{
|
|
|
- label: "高温中暑",
|
|
|
- value: "高温中暑",
|
|
|
+ label: '高温中暑',
|
|
|
+ value: '高温中暑'
|
|
|
},
|
|
|
{
|
|
|
- label: "疟疾",
|
|
|
- value: "疟疾",
|
|
|
+ label: '疟疾',
|
|
|
+ value: '疟疾'
|
|
|
},
|
|
|
{
|
|
|
- label: "登革热",
|
|
|
- value: "登革热",
|
|
|
+ label: '登革热',
|
|
|
+ value: '登革热'
|
|
|
},
|
|
|
{
|
|
|
- label: "猩红热",
|
|
|
- value: "猩红热",
|
|
|
+ label: '猩红热',
|
|
|
+ value: '猩红热'
|
|
|
},
|
|
|
{
|
|
|
- label: "聚集性呕吐腹泻",
|
|
|
- value: "聚集性呕吐腹泻",
|
|
|
- },
|
|
|
-]);
|
|
|
+ label: '聚集性呕吐腹泻',
|
|
|
+ value: '聚集性呕吐腹泻'
|
|
|
+ }
|
|
|
+])
|
|
|
|
|
|
-const timeSelect = ref("");
|
|
|
+const timeSelect = ref([])
|
|
|
const timeArr = ref([
|
|
|
{
|
|
|
- label: "当年",
|
|
|
- value: "当年",
|
|
|
+ label: '当年',
|
|
|
+ value: '当年'
|
|
|
},
|
|
|
{
|
|
|
- label: "当月",
|
|
|
- value: "当月",
|
|
|
+ label: '当月',
|
|
|
+ value: '当月'
|
|
|
},
|
|
|
{
|
|
|
- label: "当日",
|
|
|
- value: "当日",
|
|
|
- },
|
|
|
-]);
|
|
|
+ label: '当日',
|
|
|
+ value: '当日'
|
|
|
+ }
|
|
|
+])
|
|
|
|
|
|
//风险等级
|
|
|
// const riskLevelList = ref([
|
|
@@ -288,17 +306,35 @@ const timeArr = ref([
|
|
|
// },
|
|
|
// ]);
|
|
|
|
|
|
-const handleRiskLevel = (item) => {
|
|
|
- item.value = !item.value;
|
|
|
-};
|
|
|
+const handleRiskLevel = item => {
|
|
|
+ item.value = !item.value
|
|
|
+}
|
|
|
+
|
|
|
+const handleDeviceLevel = item => {
|
|
|
+ item.value = !item.value
|
|
|
+}
|
|
|
|
|
|
-const handleDeviceLevel = (item) => {
|
|
|
- item.value = !item.value;
|
|
|
-};
|
|
|
+const handleInstitutionLevel = item => {
|
|
|
+ item.value = !item.value
|
|
|
+}
|
|
|
|
|
|
-const handleInstitutionLevel = (item) => {
|
|
|
- item.value = !item.value;
|
|
|
-};
|
|
|
+const formatTimeRange = range => {
|
|
|
+ if (!range || range.length !== 2) return ''
|
|
|
+ const [start, end] = range
|
|
|
+ return `起:${formatDate(start)}\n止:${formatDate(end)}`
|
|
|
+}
|
|
|
+
|
|
|
+const formatDate = val => {
|
|
|
+ if (!val) return ''
|
|
|
+ const date = new Date(val)
|
|
|
+ const y = date.getFullYear()
|
|
|
+ const m = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
+ const d = String(date.getDate()).padStart(2, '0')
|
|
|
+ const h = String(date.getHours()).padStart(2, '0')
|
|
|
+ const min = String(date.getMinutes()).padStart(2, '0')
|
|
|
+ const s = String(date.getSeconds()).padStart(2, '0')
|
|
|
+ return `${y}-${m}-${d} ${h}:${min}:${s}`
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
@@ -306,19 +342,26 @@ const handleInstitutionLevel = (item) => {
|
|
|
padding: 15px 20px;
|
|
|
width: 217px;
|
|
|
// height: 750px;
|
|
|
- background-image: url("../../../../assets/img/撒点弹窗.png");
|
|
|
+ background-image: url('../../../../assets/img/撒点弹窗.png');
|
|
|
background-size: 100% 100%;
|
|
|
z-index: 99;
|
|
|
+ overflow: hidden;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
.legend-item {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
margin: 11px 0;
|
|
|
+ overflow: hidden;
|
|
|
.icon-box {
|
|
|
width: 28px;
|
|
|
height: 28px;
|
|
|
img {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
.icon-box-fill {
|
|
@@ -343,12 +386,12 @@ const handleInstitutionLevel = (item) => {
|
|
|
.switch-box {
|
|
|
width: 47px;
|
|
|
height: 26px;
|
|
|
- background-image: url("../../../../assets/img/Component 15(2).png");
|
|
|
+ background-image: url('../../../../assets/img/Component 15(2).png');
|
|
|
background-size: 100% 100%;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
.switchOpen {
|
|
|
- background-image: url("../../../../assets/img/Component 14.png");
|
|
|
+ background-image: url('../../../../assets/img/Component 14.png');
|
|
|
}
|
|
|
.legend-select {
|
|
|
width: 146px;
|
|
@@ -358,12 +401,7 @@ const handleInstitutionLevel = (item) => {
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
border: 1px solid #45d2ff;
|
|
|
border-bottom: 1px solid #45d2ff;
|
|
|
- border-image: linear-gradient(
|
|
|
- 174deg,
|
|
|
- rgba(154, 249, 255, 1),
|
|
|
- rgba(111, 246, 255, 0.3)
|
|
|
- )
|
|
|
- 1 1;
|
|
|
+ border-image: linear-gradient(174deg, rgba(154, 249, 255, 1), rgba(111, 246, 255, 0.3)) 1 1;
|
|
|
.el-select__wrapper {
|
|
|
background-color: transparent !important;
|
|
|
box-shadow: none;
|
|
@@ -377,7 +415,7 @@ const handleInstitutionLevel = (item) => {
|
|
|
}
|
|
|
}
|
|
|
.line-box {
|
|
|
- background-image: url("../../../../assets/img/Line 550.png");
|
|
|
+ background-image: url('../../../../assets/img/Line 550.png');
|
|
|
height: 2px;
|
|
|
background-size: 100% 100%;
|
|
|
}
|
|
@@ -396,5 +434,54 @@ const handleInstitutionLevel = (item) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+.el-date-table td.in-range .el-date-table-cell {
|
|
|
+ background-color: #0c6d88;
|
|
|
+}
|
|
|
+
|
|
|
+.el-date-table td .el-date-table-cell:hover {
|
|
|
+ background-color: #052c4f !important;
|
|
|
+}
|
|
|
+.el-picker-panel__footer {
|
|
|
+ .el-picker-panel__link-btn {
|
|
|
+ background: #052c4f;
|
|
|
+ color: #ffffff;
|
|
|
+ border: 1px solid transparent;
|
|
|
+ }
|
|
|
+ .el-picker-panel__link-btn:hover {
|
|
|
+ background: #2769a0 !important;
|
|
|
+ color: #ffffff;
|
|
|
+ border: 1px solid transparent;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.fade-slide-enter-active,
|
|
|
+.fade-slide-leave-active {
|
|
|
+ transition: all 0.3s ease;
|
|
|
+}
|
|
|
+.fade-slide-enter-from,
|
|
|
+.fade-slide-leave-to {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateY(-10px);
|
|
|
+}
|
|
|
|
|
|
+.date_picker_custom-class {
|
|
|
+ position: absolute !important;
|
|
|
+ top: 550px !important;
|
|
|
+ z-index: 999; /* 保证弹窗在其他元素上方 */
|
|
|
+ // max-height: 300px;
|
|
|
+ // overflow-y: auto;
|
|
|
+}
|
|
|
+.date-picker-container{
|
|
|
+ margin-left: 15px;
|
|
|
+}
|
|
|
+.el-input__inner{
|
|
|
+ color: #ffffff;
|
|
|
+}
|
|
|
+.el-date-editor .el-range-input{
|
|
|
+ color: #ffffff;
|
|
|
+}
|
|
|
+.el-date-editor .el-range__icon{
|
|
|
+ display: none;
|
|
|
+}
|
|
|
</style>
|
|
|
+<style scoped></style>
|