添加动画状态管理变量 isAnimating,并实现平滑的弹出和收回动画效果 修改关联关系图的显示逻辑,在动画播放期间保持元素可见 添加 CSS 动画关键帧和样式类来处理动画效果
4448 lines
129 KiB
Vue
4448 lines
129 KiB
Vue
<template>
|
||
<!-- <div ref="centerBorder"
|
||
class="absolute translate-x-1/2 translate-y-1/2 border-[2px] border-dashed rounded-[0.25rem] border-gray-600">
|
||
</div> -->
|
||
<!-- 右边的弹出窗体 -->
|
||
<nut-popup position="right" v-model:visible="state.show1" :style="{ width: state.width, height: state.height }">
|
||
<button @click="RefreshData" class="w-full bg-red-300">确定</button>
|
||
</nut-popup>
|
||
|
||
<!-- <div class="w-full h-screen bg-gradient-to-tr from-green-300 via-cyan-500 to-blue-400"
|
||
:style="{ backgroundColor: basicOptions.backgroundColor }" id="mainContainer"> -->
|
||
<div class="w-full h-screen bg-gradient-to-b from-blue-800 to-gray-800 relative overflow-hidden" id="mainContainer">
|
||
<!-- 科技感背景元素 -->
|
||
<div class="absolute inset-0 w-full h-full overflow-hidden">
|
||
<div
|
||
class="absolute top-0 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-cyan-500 to-transparent opacity-70">
|
||
</div>
|
||
<div
|
||
class="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-cyan-500 to-transparent opacity-70">
|
||
</div>
|
||
<div
|
||
class="absolute top-0 left-0 h-full w-[2px] bg-gradient-to-b from-transparent via-cyan-500 to-transparent opacity-70">
|
||
</div>
|
||
<div
|
||
class="absolute top-0 right-0 h-full w-[2px] bg-gradient-to-b from-transparent via-cyan-500 to-transparent opacity-70">
|
||
</div>
|
||
<!-- 科技感图案 -->
|
||
<div class="absolute top-10 left-10 w-[200px] h-[200px] border-l-2 border-t-2 border-cyan-500 opacity-20"></div>
|
||
<div class="absolute bottom-10 right-10 w-[200px] h-[200px] border-r-2 border-b-2 border-cyan-500 opacity-20">
|
||
</div>
|
||
<div
|
||
class="absolute top-0 left-0 w-full h-full bg-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIj48ZyBmaWxsPSJub25lIiBzdHJva2U9IiMwYmI3ZmYiIHN0cm9rZS13aWR0aD0iMC4yIiBvcGFjaXR5PSIwLjIiPjxwYXRoIGQ9Ik0yMCAyMCBMMCAyMCBMMCA0MCIvPjxwYXRoIGQ9Ik0yMCAyMCBMNDAgMjAgTDQwIDQwIi8+PHBhdGggZD0iTTIwIDIwIEwwIDIwIEwwIDAiLz48cGF0aCBkPSJNMjAgMjAgTDQwIDIwIEw0MCAwIi8+PC9nPjwvc3ZnPg==')] bg-repeat opacity-5">
|
||
</div>
|
||
</div>
|
||
<!-- 关闭按钮 -->
|
||
<router-link to="/navigation" style="z-index: 100" class="card1">
|
||
<div class="card-icon1">❌</div>
|
||
</router-link>
|
||
|
||
<!-- 标题 -->
|
||
<div class="w-full h-[52px]" id="containerTitle">
|
||
<div
|
||
class="flex w-full absolute justify-center flex-col items-center text-4xl py-2 z-10 pt-10 text-white font-bold">
|
||
<div class="relative">
|
||
<span class="text-cyan-500">上海市</span>
|
||
<span class="text-white">食品安全综合指数</span>
|
||
<div
|
||
class="absolute -bottom-2 left-0 w-full h-[3px] bg-gradient-to-r from-transparent via-cyan-500 to-transparent">
|
||
</div>
|
||
</div>
|
||
<!-- <div class="text-xl pt-4">总分数:{{ AllCourse }}分</div> -->
|
||
</div>
|
||
</div>
|
||
<!-- 仪表盘 -->
|
||
<vue-draggable-resizable ref="yibiao1" style="border: none; left: 49%; top: 16.5%; z-index: 999"
|
||
:draggable="draggableBoolean" :resizable="resizableBoolean">
|
||
<div class="flex items-center justify-center w-96 h-48 rounded-md bg-transparent" ref="yibiao"></div>
|
||
</vue-draggable-resizable>
|
||
|
||
<!-- 选项 -->
|
||
<div class="w-full absolute flex justify-center pt-12 gap-4 z-20">
|
||
<div
|
||
class="relative bg-transparent backdrop-blur-sm border border-blue-300/50 rounded px-3 py-2 shadow-[0_0_8px_rgba(59,130,246,0.3)]">
|
||
<!-- 新增年份下拉框 -->
|
||
<el-select v-model="yearValue" class="m-1 text-white font-medium bg-transparent" placeholder="年份"
|
||
@change="SelectBlur" style="width: 100px">
|
||
<el-option v-for="item in yearOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
<!-- <div
|
||
class="absolute -top-3 left-2 bg-transparent backdrop-blur-sm px-2 text-xs text-blue-300 font-medium border-x border-t border-blue-300/50">
|
||
筛选条件</div> -->
|
||
<el-select v-model="monthValue" class="m-1 text-white font-medium bg-transparent" placeholder="月份"
|
||
@change="SelectBlur" style="width: 100px">
|
||
<el-option v-for="item in monthOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
<el-select v-model="districtValue" class="m-1 text-white font-medium bg-transparent" placeholder="辖区"
|
||
@change="SelectBlur" style="width: 100px">
|
||
<el-option v-for="item in districtOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
<el-select v-model="stageValue" class="m-1 text-white font-medium bg-transparent" placeholder="环节"
|
||
@change="SelectBlur" style="width: 100px">
|
||
<el-option v-for="item in stageOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 左1 -->
|
||
<vue-draggable-resizable ref="refWoTe1" style="border: none; z-index: 999" :draggable="draggableBoolean"
|
||
:resizable="resizableBoolean">
|
||
<div class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500"
|
||
ref="main1"></div>
|
||
</vue-draggable-resizable>
|
||
<!-- 左2 -->
|
||
<vue-draggable-resizable ref="refWoTe2" style="border: none; z-index: 999" :draggable="draggableBoolean"
|
||
:resizable="resizableBoolean">
|
||
<div class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500"
|
||
ref="main2"></div>
|
||
</vue-draggable-resizable>
|
||
<!-- 左3 -->
|
||
<vue-draggable-resizable ref="refWoTe3" style="border: none; z-index: 999" :draggable="draggableBoolean"
|
||
:resizable="resizableBoolean">
|
||
<div class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500"
|
||
ref="main3"></div>
|
||
</vue-draggable-resizable>
|
||
|
||
<!-- 右1 -->
|
||
<vue-draggable-resizable ref="refWoTe4" style="border: none; z-index: 999" :draggable="draggableBoolean"
|
||
:resizable="resizableBoolean">
|
||
<div class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500"
|
||
ref="main4">
|
||
<div class="flex justify-around text-white">
|
||
<div class="p-2 flex flex-col font-semibold items-center">
|
||
<div class="flex flex-row">
|
||
<img src="../../public/image/shiwuzhongdu.png" class="w-8 h-8 rounded-full" />食物中毒控制率
|
||
</div>
|
||
<div>{{ SecondLevelMetricValues.foodPoisoningIncidence }}分</div>
|
||
</div>
|
||
<div class="p-2 flex flex-col font-semibold items-center">
|
||
<div class="flex flex-row">
|
||
<img src="../../public/image/manyidu.png" class="w-8 h-8 rounded-full" />市民满意度
|
||
</div>
|
||
<div>{{ SecondLevelMetricValues.citizenSatisfaction }}分</div>
|
||
</div>
|
||
<div class="p-2 flex flex-col font-semibold items-center">
|
||
<div class="flex flex-row">
|
||
<img src="../../public/image/zhixiaodu.png" class="w-8 h-8 rounded-full" />市民知晓度
|
||
</div>
|
||
<div>{{ SecondLevelMetricValues.citizenAwareness }}分</div>
|
||
</div>
|
||
<!-- <div class="text-xl p-2 flex flex-col font-semibold items-center">
|
||
<div class="flex flex-row">
|
||
<img
|
||
src="../../public/image/qiyerenzhenglv.jpg"
|
||
class="w-8 h-8 rounded-full"
|
||
/>企业管理体系认证率
|
||
</div>
|
||
<div>{{ SecondLevelMetricValues.certificationRate }}分</div>
|
||
</div> -->
|
||
</div>
|
||
</div>
|
||
</vue-draggable-resizable>
|
||
<!-- 右2 -->
|
||
<vue-draggable-resizable ref="refWoTe5" style="border: none; z-index: 999;" :draggable="draggableBoolean"
|
||
:resizable="resizableBoolean">
|
||
<div class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500"
|
||
ref="main5">
|
||
<div class="scroll-wrapper" v-if="defaultShow">
|
||
<div class="scroll-header">
|
||
<span class="scroll-header-text">检测项目</span>
|
||
<span class="scroll-header-text">食品小类</span>
|
||
<span class="scroll-header-text">被抽样单位名称</span>
|
||
<span class="scroll-header-text">抽样时间</span>
|
||
<span class="">风险等级</span>
|
||
</div>
|
||
<div class="scroll-container">
|
||
<vue3ScrollSeamless :dataList="scrollData" :classOptions="classOptions">
|
||
<div v-for="(item, index) in scrollData" :key="index">
|
||
<div class="scroll-item">
|
||
<span class="scroll-item-text">{{ item.xiangmu }}</span>
|
||
<span class="scroll-item-text">{{ item.xiaolei }}</span>
|
||
<span class="scroll-item-text">{{ item.danwei }}</span>
|
||
<span class="scroll-item-text">{{ item.time }}</span>
|
||
<span class="" style="
|
||
width: 20px;
|
||
height: 10px;
|
||
color: black;
|
||
text-align: center;
|
||
margin: 2px 10px 0px 10px;
|
||
" :style="{ backgroundColor: item.dengji }">-</span>
|
||
</div>
|
||
</div>
|
||
</vue3ScrollSeamless>
|
||
</div>
|
||
</div>
|
||
|
||
<swiper :modules="modules" :loop="true" :slides-per-view="1" :space-between="50"
|
||
:autoplay="{ delay: 3000, disableOnInteraction: true }" :navigation="navigation"
|
||
:pagination="{ clickable: true }" :scrollbar="{ draggable: false }" class="swiperBox"
|
||
@slideChange="onSlideChange" v-if="!defaultShow" ref="swiperRef" id="swiperBox">
|
||
<swiper-slide v-if="choujianShow">
|
||
<div class="scroll-wrapper">
|
||
<div class="scroll-header-title">首发预警</div>
|
||
<div class="scroll-header">
|
||
<span class="scroll-header-text">检测项目</span>
|
||
<span class="scroll-header-text">食品小类</span>
|
||
<span class="scroll-header-text">被抽样单位名称</span>
|
||
<span class="scroll-header-text">抽样时间</span>
|
||
<span class="">风险等级</span>
|
||
</div>
|
||
<div class="scroll-container">
|
||
<vue3ScrollSeamless :dataList="choujianShoufaData" :classOptions="classOptions">
|
||
<div v-for="(item, index) in choujianShoufaData" :key="index">
|
||
<div class="scroll-item">
|
||
<span class="scroll-item-text">{{ item.xiangmu }}</span>
|
||
<span class="scroll-item-text">{{ item.xiaolei }}</span>
|
||
<span class="scroll-item-text">{{ item.danwei }}</span>
|
||
<span class="scroll-item-text">{{ item.time }}</span>
|
||
<span class="" style="
|
||
width: 20px;
|
||
height: 10px;
|
||
color: black;
|
||
text-align: center;
|
||
margin: 2px 10px 0px 10px;
|
||
" :style="{ backgroundColor: item.dengji }">-</span>
|
||
</div>
|
||
</div>
|
||
</vue3ScrollSeamless>
|
||
</div>
|
||
</div>
|
||
</swiper-slide>
|
||
<swiper-slide v-if="choujianShow">
|
||
<div class="scroll-wrapper">
|
||
<div class="scroll-header-title">高发预警</div>
|
||
<div class="scroll-header">
|
||
<span class="scroll-header-text">检测项目</span>
|
||
<span class="scroll-header-text">食品小类</span>
|
||
<span class="scroll-header-text">抽检件数</span>
|
||
<span class="scroll-header-text">不合格率(%)</span>
|
||
<span class="">风险等级</span>
|
||
</div>
|
||
<div class="scroll-container">
|
||
<vue3ScrollSeamless :dataList="choujianGaofaData" :classOptions="classOptions">
|
||
<div v-for="(item, index) in choujianGaofaData" :key="index">
|
||
<div class="scroll-item">
|
||
<span class="scroll-item-text">{{ item.xiangmu }}</span>
|
||
<span class="scroll-item-text">{{ item.xiaolei }}</span>
|
||
<span class="scroll-item-text">{{ item.choujian }}</span>
|
||
<span class="scroll-item-text">{{ item.buhegelv }}</span>
|
||
<span class="" style="
|
||
width: 20px;
|
||
height: 10px;
|
||
color: black;
|
||
text-align: center;
|
||
margin: 2px 10px 0px 10px;
|
||
" :style="{ backgroundColor: item.dengji }">-</span>
|
||
</div>
|
||
</div>
|
||
</vue3ScrollSeamless>
|
||
</div>
|
||
</div>
|
||
</swiper-slide>
|
||
<swiper-slide v-if="choujianShow">
|
||
<div class="w-full h-full">
|
||
<div ref="main7" style="width: 100%; height: 100%"></div>
|
||
</div>
|
||
</swiper-slide>
|
||
<swiper-slide v-if="tousuShow">
|
||
<div class="scroll-wrapper">
|
||
<div class="scroll-header-title">高发预警</div>
|
||
<div class="scroll-header">
|
||
<span class="scroll-header-text">投诉环节</span>
|
||
<span class="scroll-header-text">投诉问题种类</span>
|
||
<span class="scroll-header-text">投诉率</span>
|
||
<span class="">风险等级</span>
|
||
</div>
|
||
<div class="scroll-container">
|
||
<vue3ScrollSeamless :dataList="jubaoGaofaData" :classOptions="classOptions">
|
||
<div v-for="(item, index) in jubaoGaofaData" :key="index" @click="handleRowClick(item, index)">
|
||
<div class="scroll-item">
|
||
<span class="scroll-item-text">{{ item.huanjie }}</span>
|
||
<span class="scroll-item-text">{{ item.zhonglei }}</span>
|
||
<span class="scroll-item-text">{{ item.tousulv }}</span>
|
||
<span class="" style="
|
||
width: 20px;
|
||
height: 10px;
|
||
color: black;
|
||
text-align: center;
|
||
margin: 2px 10px 0px 10px;
|
||
" :style="{ backgroundColor: item.dengji }">-</span>
|
||
</div>
|
||
</div>
|
||
</vue3ScrollSeamless>
|
||
</div>
|
||
</div>
|
||
</swiper-slide>
|
||
<swiper-slide v-if="tousuShow">
|
||
<div class="scroll-wrapper">
|
||
<div class="scroll-header-title">频发预警</div>
|
||
<div class="scroll-header">
|
||
<span class="scroll-header-text">被投诉主体名称</span>
|
||
<span class="scroll-header-text">被投诉产品类别</span>
|
||
<span class="scroll-header-text">抽检合格率</span>
|
||
<span class="scroll-header-text">被投诉问题种类</span>
|
||
<span class="scroll-header-text">被投诉问题数</span>
|
||
<span class="">风险等级</span>
|
||
</div>
|
||
<div class="scroll-container">
|
||
<vue3ScrollSeamless :dataList="jubaoPinfaData" :classOptions="classOptions">
|
||
<div v-for="(item, index) in jubaoPinfaData" :key="index">
|
||
<div class="scroll-item">
|
||
<span class="scroll-item-text">{{ item.zhuti }}</span>
|
||
<span class="scroll-item-text">{{ item.leibie }}</span>
|
||
<span class="scroll-item-text">{{ item.hegelv }}</span>
|
||
<span class="scroll-item-text">{{ item.zhonglei }}</span>
|
||
<span class="scroll-item-text">{{ item.wentishu }}</span>
|
||
<span class="" style="
|
||
width: 20px;
|
||
height: 10px;
|
||
color: black;
|
||
text-align: center;
|
||
margin: 2px 10px 0px 10px;
|
||
" :style="{ backgroundColor: item.dengji }">-</span>
|
||
</div>
|
||
</div>
|
||
</vue3ScrollSeamless>
|
||
</div>
|
||
</div>
|
||
</swiper-slide>
|
||
<div class="swiper-button-prev" @click.stop="prevEl" />
|
||
<!--左箭头。如果放置在swiper外面,需要自定义样式。-->
|
||
<div class="swiper-button-next" @click.stop="nextEl" />
|
||
<!--右箭头。如果放置在swiper外面,需要自定义样式。-->
|
||
<!-- 如果需要滚动条 -->
|
||
<!-- <div class="swiper-scrollbar"></div> -->
|
||
</swiper>
|
||
|
||
<div class="scroll-wrapper" v-if="zhifaShow">
|
||
<div class="w-full h-full">
|
||
<div ref="main8" style="width: 100%; height: 100%"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</vue-draggable-resizable>
|
||
<!-- 右3 -->
|
||
<vue-draggable-resizable ref="refWoTe6" style="border: none; z-index: 999" :draggable="draggableBoolean"
|
||
:resizable="resizableBoolean" v-show="!relationShow && !isAnimating">
|
||
<div
|
||
class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500 overflow-hidden"
|
||
ref="main6">
|
||
|
||
</div>
|
||
</vue-draggable-resizable>
|
||
<!-- 右下角按钮 -->
|
||
<div ref="fancyBtn"
|
||
class=" fixed z-[9999] bottom-10 right-7 px-3 py-1 rounded-full bg-gradient-to-r from-blue-500 via-cyan-400 to-purple-500 shadow-lg text-white font-bold text-lg cursor-pointer transition-all duration-300 ease-in-out hover:scale-110 hover:shadow-2xl active:scale-95 active:brightness-90 ring-2 ring-white/30 ring-offset-2 ring-offset-black backdrop-blur-md overflow-hidden"
|
||
@click="handleFancyClick" style="user-select: none;">
|
||
关联关系图
|
||
<span ref="ripple" class="ripple"></span>
|
||
</div>
|
||
<div
|
||
class="flex items-center justify-center w-96 h-48 border-2 border-dashed rounded border-gray-500 overflow-hidden z-[999] fixed bottom-10 right-7"
|
||
ref="main9"
|
||
:class="{
|
||
'animate-popup': isAnimating && relationShow,
|
||
'animate-shrink': isAnimating && !relationShow,
|
||
'opacity-0 scale-0': !relationShow && !isAnimating
|
||
}"
|
||
v-show="relationShow || isAnimating"
|
||
style="transform-origin: bottom right;">
|
||
|
||
</div>
|
||
|
||
<!-- 底部 -->
|
||
<div class="w-full absolute bottom-2 flex justify-center text-white">
|
||
<div class="flex items-center justify-center w-96 h-48" ref="timeline"></div>
|
||
</div>
|
||
|
||
<div class="shanghaimap">
|
||
<!-- <EChartsMap /> -->
|
||
<!-- <div id="streetMapEcharts" style="width: 320%; height: 50%;"></div> -->
|
||
<div id="streetMapEcharts" style="width: 100%; height: 100%"></div>
|
||
</div>
|
||
|
||
<div id="tooltip" style="
|
||
position: absolute;
|
||
background-color: #fff;
|
||
border: 1px solid #ddd;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
pointer-events: none;
|
||
z-index: 9999;
|
||
" v-show="isTooltipVisible"></div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import VueDraggableResizable from "vue-draggable-resizable/src/components/vue-draggable-resizable.vue";
|
||
import "vue-draggable-resizable/dist/VueDraggableResizable.css";
|
||
import { onMounted, reactive, ref, watch, onBeforeUnmount, nextTick } from "vue";
|
||
import BarShow from "../components/barshow.vue";
|
||
import shangHaiJieDao from "../mapjson/shangHaiJieDao.json";
|
||
import shangHaiXiaQu from "../mapjson/shanghaiXiaQu.json";
|
||
import CnFxJiedao2 from "../mapjson/CnFxJiedao2.json";
|
||
import type { GeoJSONSourceInput } from "echarts/types/src/coord/geo/geoTypes";
|
||
import { vue3ScrollSeamless } from "vue3-scroll-seamless";
|
||
|
||
import EChartsMap from "./eChartsMap.vue";
|
||
|
||
import { Sketch } from "@ans1998/vue3-color";
|
||
import {
|
||
getMapLayoutList,
|
||
loadMapOptions,
|
||
removeMapLayout,
|
||
updateMapLayout,
|
||
getDistinguishValue,
|
||
getCheckMonitoringValueStreet,
|
||
getCheckAssessmentValueStreet,
|
||
getIstrativeSanctionValueStreet,
|
||
getComplaintReportValueStreet,
|
||
getInformationTracingValueStreet,
|
||
getLawEnforcementInspectionValueStreet,
|
||
getAllCourse,
|
||
getSecondLevelMetricValues,
|
||
getAllData,
|
||
getStreetAllData,
|
||
} from "../api/SettingAPIDaSai";
|
||
import Enumerable from "linq";
|
||
import { first, reduce } from "lodash";
|
||
import { ElMessage } from "element-plus";
|
||
import { router } from "../router";
|
||
import headMenu from "../components/headMenu.vue";
|
||
import * as echarts from "echarts";
|
||
import "echarts-wordcloud";
|
||
import * as d3 from "d3";
|
||
|
||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||
import "swiper/css";
|
||
import "swiper/less/navigation";
|
||
import "swiper/less/pagination";
|
||
import {
|
||
Autoplay,
|
||
Navigation,
|
||
Pagination,
|
||
Scrollbar,
|
||
A11y,
|
||
} from "swiper/modules";
|
||
|
||
// 新增 API 引入
|
||
import { getRelationshipNetwork } from "../api/compositeIndex";
|
||
|
||
//各个区的值
|
||
interface DistinguishValueInterface {
|
||
[key: string]: number;
|
||
}
|
||
|
||
// 新增类型
|
||
interface TimelineData {
|
||
timeLabel: string;
|
||
realScores: number[];
|
||
predictScores: number[];
|
||
}
|
||
|
||
// 类型定义
|
||
type TimePeriod =
|
||
| "上三个月"
|
||
| "上二个月"
|
||
| "上一个月"
|
||
| "当前月"
|
||
| "下一个月"
|
||
| "下二个月"
|
||
| "下三个月";
|
||
type ScoreData = {
|
||
real: number[];
|
||
predict: number[];
|
||
};
|
||
|
||
// 响应式数据
|
||
const timelineData = ref<TimelineData[]>([]);
|
||
const currentTimeIndex = ref(0);
|
||
|
||
//改变地图大小
|
||
const changeSizeValue = ref(1.15);
|
||
//设置地图左右移动
|
||
const changePositionX = ref(1.02);
|
||
//设置地图上下移动
|
||
const changePositionY = ref(30);
|
||
//设置16个区是否可以移动
|
||
const draggableBoolean = ref(false);
|
||
//设置16个区是否可以放大缩小
|
||
const resizableBoolean = ref(false);
|
||
//总分数
|
||
const AllCourse = ref(100);
|
||
//tooltip框显示
|
||
const isTooltipVisible = ref(false);
|
||
|
||
//右2图表默认展示
|
||
const defaultShow = ref(true);
|
||
|
||
const classOptions = {
|
||
// 滚动步长
|
||
step: 0.1,
|
||
limitMoveNum: 9,
|
||
};
|
||
const navigation = ref({
|
||
nextEl: ".swiper-button-next",
|
||
prevEl: ".swiper-button-prev",
|
||
});
|
||
// 在modules加入要使用的模块
|
||
const modules = [Autoplay, Pagination, Navigation, Scrollbar];
|
||
const prevEl = () => {
|
||
console.log("上一张");
|
||
};
|
||
const nextEl = () => {
|
||
console.log("下一张");
|
||
};
|
||
// 更改当前活动swiper
|
||
const onSlideChange = (swiper: any) => {
|
||
// swiper是当前轮播的对象,里面可以获取到当前swiper的所有信息,当前索引是activeIndex
|
||
console.log(swiper.activeIndex, "活动swiper更改");
|
||
};
|
||
|
||
const swiperBoxHeight = ref("300px");
|
||
|
||
const choujianShow = ref(false);
|
||
const tousuShow = ref(false);
|
||
const zhifaShow = ref(false);
|
||
//
|
||
const littlemonth = ref(-1);
|
||
|
||
// 下拉框"年份"值
|
||
const yearValue = ref("2023");
|
||
// 下拉框"年份"option
|
||
const yearOptions = [
|
||
{
|
||
value: "2021",
|
||
label: "2021",
|
||
},
|
||
{
|
||
value: "2022",
|
||
label: "2022",
|
||
},
|
||
{
|
||
value: "2023",
|
||
label: "2023",
|
||
},
|
||
// 可以根据需要添加更多年份
|
||
];
|
||
|
||
//下拉框"月份"值
|
||
const monthValue = ref("4");
|
||
// 下拉框"月份"option
|
||
const monthOptions = [
|
||
{
|
||
value: "",
|
||
label: "全部",
|
||
},
|
||
{
|
||
value: "1",
|
||
label: "一月",
|
||
},
|
||
{
|
||
value: "2",
|
||
label: "二月",
|
||
},
|
||
{
|
||
value: "3",
|
||
label: "三月",
|
||
},
|
||
{
|
||
value: "4",
|
||
label: "四月",
|
||
},
|
||
{
|
||
value: "5",
|
||
label: "五月",
|
||
},
|
||
// {
|
||
// value: "6",
|
||
// label: "六月",
|
||
// }
|
||
// ,
|
||
// {
|
||
// value: "7",
|
||
// label: "七月",
|
||
// },
|
||
// {
|
||
// value: "8",
|
||
// label: "八月",
|
||
// },
|
||
// {
|
||
// value: "9",
|
||
// label: "九月",
|
||
// },
|
||
// {
|
||
// value: "10",
|
||
// label: "十月",
|
||
// },
|
||
// {
|
||
// value: "11",
|
||
// label: "十一月",
|
||
// },
|
||
// {
|
||
// value: "12",
|
||
// label: "十二月",
|
||
// },
|
||
];
|
||
|
||
//下拉框"市区"值
|
||
const districtValue = ref("上海市");
|
||
//下拉框"市区"option
|
||
const districtOptions = [
|
||
{
|
||
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: "金山区",
|
||
// label: "金山区",
|
||
// },
|
||
// {
|
||
// value: "松江区",
|
||
// label: "松江区",
|
||
// },
|
||
// {
|
||
// value: "青浦区",
|
||
// label: "青浦区",
|
||
// },
|
||
// {
|
||
// value: "崇明区",
|
||
// label: "崇明区",
|
||
// },
|
||
];
|
||
|
||
// 背景页面颜色:
|
||
const webPageBackgroundColor = "#F0F0F0";
|
||
//图表颜色
|
||
const echartsColorArray = [
|
||
"#5470c6",
|
||
"#91cc75",
|
||
"#fac858",
|
||
"#ee6666",
|
||
"#73c0de",
|
||
"#3ba272",
|
||
"#fc8452",
|
||
"#9a60b4",
|
||
"#ea7ccc",
|
||
];
|
||
// const echartsColorArray = ['#FF00FF', '#00FF00'];
|
||
|
||
// 六个表的分数
|
||
const checkMonitoringScore = ref(100); //安全抽检(1表)
|
||
const checkAssessmentScore = ref(100); //抽查考核(2表)
|
||
const istrativeSanctionScore = ref(100); //行政处罚(3表)
|
||
const complaintReportScore = ref(100); //投诉举报(4表)
|
||
const informationTracingScore = ref(100); //信息追溯(5表)
|
||
const lawEnforcementInspectionScore = ref(100); //执法检查(6表)
|
||
|
||
//六个表的值
|
||
const checkMonitoringData = ref(); //安全抽检(1表)
|
||
const checkAssessmentPost = ref(); //抽查考核(2表)岗位
|
||
const checkAssessmentPassRate = ref(); //抽查考核(2表)合格率
|
||
const checkAssessmentNumber = ref(); //抽查考核(2表)考核人次
|
||
const istrativeSanctionData = ref(); //行政处罚(3表)
|
||
const complaintReportData = ref(); //投诉举报(4表)
|
||
const informationTracingCompanyType = ref(); //信息追溯(5表)企业分类名
|
||
const informationTracingCompanyTypeValue = ref(); //信息追溯(5表)企业分类值
|
||
const lawEnforcementInspectionData = ref(); //执法检查(6表)
|
||
|
||
// 二级指标的值
|
||
const SecondLevelMetricValues = ref({
|
||
foodPoisoningIncidence: 100,
|
||
citizenSatisfaction: 100,
|
||
citizenAwareness: 100,
|
||
certificationRate: 100,
|
||
});
|
||
// 下拉框"环节"值
|
||
const stageValue = ref("");
|
||
// 下拉框"环节"option
|
||
const stageOptions = [
|
||
{
|
||
value: "",
|
||
label: "全部",
|
||
},
|
||
{
|
||
value: "生产环节",
|
||
label: "生产环节",
|
||
},
|
||
{
|
||
value: "销售环节",
|
||
label: "销售环节",
|
||
},
|
||
{
|
||
value: "餐饮环节",
|
||
label: "餐饮环节",
|
||
},
|
||
];
|
||
///新增的展示框图界面
|
||
const arrStepShow = ref(["", "", "", ""]);
|
||
|
||
//新增展示框图的颜色数据
|
||
const curArrColor = ref();
|
||
|
||
const arrColorDef = {
|
||
red: [
|
||
"#FEF2F2",
|
||
"#FEE2E2",
|
||
"#FECACA",
|
||
"#FCA5A5",
|
||
"#F87171",
|
||
"#EF4444",
|
||
"#DC2626",
|
||
"#B91C1C",
|
||
"#991B1B",
|
||
"#7F1D1D",
|
||
],
|
||
green: [
|
||
"#ECFDF5",
|
||
"#D1FAE5",
|
||
"#A7F3D0",
|
||
"#6EE7B7",
|
||
"#34D399",
|
||
"#10B981",
|
||
"#059669",
|
||
"#047857",
|
||
"#065F46",
|
||
"#064E3B",
|
||
],
|
||
yellow: [
|
||
"#FFFBEB",
|
||
"#FEF3C7",
|
||
"#FDE68A",
|
||
"#FCD34D",
|
||
"#FBBF24",
|
||
"#F59E0B",
|
||
"#D97706",
|
||
"#B45309",
|
||
"#92400E",
|
||
"#78350F",
|
||
],
|
||
blue: [
|
||
// "#EFF6FF",
|
||
// "#DBEAFE",
|
||
// "#BFDBFE",
|
||
// "#93C5FD",
|
||
"#60A5FA",
|
||
"#3B82F6",
|
||
// "#2563EB",
|
||
"#1D4ED8",
|
||
// "#1E40AF",
|
||
"#1E3A8A",
|
||
],
|
||
qingxin: [
|
||
"#FFFF99", // 分数段0-25
|
||
"#98FB98", // 分数段25-50
|
||
"#ADD8E6", // 分数段50-75
|
||
"#A52A2A", // 分数段75-100
|
||
],
|
||
};
|
||
//赋值测试
|
||
curArrColor.value = arrColorDef.blue;
|
||
|
||
//设置展示框图界面数据
|
||
const setStepShow = (min: number, max: number, jiange: number) => {
|
||
arrStepShow.value = [];
|
||
for (let index = 0; index < 4; index++) {
|
||
var strShow =
|
||
(min + jiange * index).toFixed(0) +
|
||
"~" +
|
||
(min + jiange * (index + 1)).toFixed(0);
|
||
arrStepShow.value.push(strShow);
|
||
}
|
||
arrStepShow.value.push((min + jiange * 4).toFixed(0) + "~" + max.toFixed(0));
|
||
|
||
//设置显示的颜色,改造成动态的方式
|
||
switch (basicOptions.radioColorType) {
|
||
case "red":
|
||
curArrColor.value = arrColorDef.red;
|
||
break;
|
||
case "yellow":
|
||
curArrColor.value = arrColorDef.yellow;
|
||
break;
|
||
case "blue":
|
||
curArrColor.value = arrColorDef.blue;
|
||
break;
|
||
case "green":
|
||
curArrColor.value = arrColorDef.green;
|
||
break;
|
||
case "qingxin":
|
||
curArrColor.value = arrColorDef.qingxin;
|
||
break;
|
||
}
|
||
|
||
// // console.log("间隔数据", arrStepShow);
|
||
};
|
||
|
||
//路由切换部分
|
||
// const radio1 = ref('上海地图')
|
||
// const getRouter=(e:any)=>{
|
||
// // console.log('路由',e);
|
||
// if (e==='全国地图') {
|
||
// router.push('/chinamap')
|
||
// }
|
||
// }
|
||
|
||
//定义每个页面的后台编号
|
||
const curId = "1";
|
||
|
||
//这个页面除了地图之外的统一配置
|
||
const basicOptions = reactive({
|
||
backgroundColor: webPageBackgroundColor, //整个界面的背景颜色
|
||
isPresetColorRange: false, //是否是使用自己的设置区间值
|
||
colorRange: ["0", "0", "0", "0", "0", "0", "0", "0", "0"], //自己设计的区间值
|
||
radioColorType: "blue", //地图的色系选择
|
||
barTitle: "各区分数", //柱状图的标题内容
|
||
barTextColor: "", //柱状图的文字颜色
|
||
isSqrt: false, //是否进行开平方的操作
|
||
});
|
||
|
||
//改变背景颜色的功能部分///////////////////////////////////////////////
|
||
const showSketch_Background = ref(false);
|
||
//const sketchBgColor_Background = ref(0);
|
||
//改变背景颜色的设置
|
||
const changSketch_Background = () => {
|
||
showSketch_Background.value = !showSketch_Background.value;
|
||
};
|
||
|
||
const changSketchButton_Background = (item: any) => {
|
||
if (item.isOk) {
|
||
// console.log("确定");
|
||
basicOptions.backgroundColor = item.activeColor;
|
||
showSketch_Background.value = false;
|
||
} else {
|
||
// // console.log("取消");
|
||
showSketch_Background.value = false;
|
||
}
|
||
};
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
//改变文字颜色的功能部分///////////////////////////////////////////////
|
||
const showSketch_barTextColor = ref(false);
|
||
//const sketchBgColor_barTextColor = ref(0);
|
||
//改变文字颜色的设置
|
||
const changSketch_barTextColor = () => {
|
||
showSketch_barTextColor.value = !showSketch_barTextColor.value;
|
||
};
|
||
|
||
const changSketchButton_barTextColor = (item: any) => {
|
||
if (item.isOk) {
|
||
// console.log("确定");
|
||
basicOptions.barTextColor = item.activeColor;
|
||
showSketch_barTextColor.value = false;
|
||
} else {
|
||
// console.log("取消");
|
||
showSketch_barTextColor.value = false;
|
||
}
|
||
};
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
const state = reactive({
|
||
show1: false,
|
||
width: "30%",
|
||
height: "100%",
|
||
});
|
||
const openDrawer = () => {
|
||
state.show1 = true;
|
||
};
|
||
|
||
//const internalInstance = getCurrentInstance()
|
||
//颜色色系设置
|
||
//const radioColorType = ref("red");
|
||
|
||
const curMax = ref(0);
|
||
|
||
//所有的拖拉框
|
||
// 崇明区
|
||
const refChongMing = ref(null);
|
||
// 浦东新区
|
||
const refPuDong = ref(null);
|
||
// 宝山区
|
||
const refBaoShan = ref(null);
|
||
// 嘉定区
|
||
const refJiaDing = ref(null);
|
||
// 青浦区
|
||
const refQingPu = ref(null);
|
||
// 金山区
|
||
const refJinShan = ref(null);
|
||
// 奉贤区
|
||
const refFengXian = ref(null);
|
||
// 松江区
|
||
const refSongJiang = ref(null);
|
||
// 闵行区
|
||
const refMinHang = ref(null);
|
||
// 徐汇区
|
||
const refXuHui = ref(null);
|
||
// 长宁区
|
||
const refChangNing = ref(null);
|
||
// 普陀区
|
||
const refPuTuo = ref(null);
|
||
// 静安区
|
||
const refJingAn = ref(null);
|
||
// 虹口区
|
||
const refHongKou = ref(null);
|
||
// 黄浦区
|
||
const refHuangPu = ref(null);
|
||
// 杨浦区
|
||
const refYangPu = ref(null);
|
||
|
||
//柱状图
|
||
const refBar = ref(null);
|
||
// 颜色图例
|
||
const refColorLegend = ref(null);
|
||
//食品大类表格
|
||
const refWoTe1 = ref(null);
|
||
const refWoTe2 = ref(null);
|
||
const refWoTe3 = ref(null);
|
||
const refWoTe4 = ref(null);
|
||
const refWoTe5 = ref(null);
|
||
const refWoTe6 = ref(null);
|
||
const yibiao1 = ref(null);
|
||
|
||
//设置动态样式颜色的值
|
||
// 崇明区
|
||
const colorChongMing = ref(null);
|
||
// 浦东新区
|
||
const colorPuDong = ref(null);
|
||
// 宝山区
|
||
const colorBaoShan = ref(null);
|
||
// 嘉定区
|
||
const colorJiaDing = ref(null);
|
||
// 青浦区
|
||
const colorQingPu = ref(null);
|
||
// 金山区
|
||
const colorJinShan = ref(null);
|
||
// 奉贤区
|
||
const colorFengXian = ref(null);
|
||
// 松江区
|
||
const colorSongJiang = ref(null);
|
||
// 闵行区
|
||
const colorMinHang = ref(null);
|
||
// 徐汇区
|
||
const colorXuHui = ref(null);
|
||
// 长宁区
|
||
const colorChangNing = ref(null);
|
||
// 普陀区
|
||
const colorPuTuo = ref(null);
|
||
// 静安区
|
||
const colorJingAn = ref(null);
|
||
// 虹口区
|
||
const colorHongKou = ref(null);
|
||
// 黄浦区
|
||
const colorHuangPu = ref(null);
|
||
// 杨浦区
|
||
const colorYangPu = ref(null);
|
||
|
||
// 柱状图
|
||
const colorBar = ref(null);
|
||
|
||
let chartRelationship: echarts.ECharts | null = null; // 需要保持图表实例引用
|
||
|
||
//const curColorType=ref("red")
|
||
//所有的拖拉框的位置参数
|
||
const curLayout = reactive({
|
||
ChongMing: { value: "0", color: "fill-red-100" },
|
||
PuDong: { value: "0", color: "fill-red-100" },
|
||
BaoShan: { value: "0", color: "fill-red-100" },
|
||
JiaDing: { value: "0", color: "fill-red-100" },
|
||
QingPu: { value: "0", color: "fill-red-100" },
|
||
JinShan: { value: "0", color: "fill-red-100" },
|
||
FengXian: { value: "0", color: "fill-red-100" },
|
||
SongJiang: { value: "0", color: "fill-red-100" },
|
||
MinHang: { value: "0", color: "fill-red-100" },
|
||
XuHui: { value: "0", color: "fill-red-100" },
|
||
ChangNing: { value: "0", color: "fill-red-100" },
|
||
PuTuo: { value: "0", color: "fill-red-100" },
|
||
JingAn: { value: "0", color: "fill-red-100" },
|
||
HongKou: { value: "0", color: "fill-red-100" },
|
||
HuangPu: { value: "0", color: "fill-red-100" },
|
||
YangPu: { value: "0", color: "fill-red-100" },
|
||
Bar: { value: "0", color: "fill-red-100" },
|
||
Options: {},
|
||
ColorLegend: {},
|
||
WoTe1: {},
|
||
WoTe2: {},
|
||
WoTe3: {},
|
||
WoTe4: {},
|
||
WoTe5: {},
|
||
WoTe6: {},
|
||
});
|
||
|
||
//当前的颜色赋值的数组
|
||
const curArrayColor: any = ref([]);
|
||
|
||
//浏览器可视页面宽度
|
||
const windowWidth = ref(1920);
|
||
//浏览器可视页面高度
|
||
const windowHeight = ref(960);
|
||
|
||
// 保存配置的结果
|
||
|
||
const btnLoad = () => {
|
||
setLayout(refWoTe1.value! as any, curLayout["WoTe1"]);
|
||
setLayout(refWoTe2.value! as any, curLayout["WoTe2"]);
|
||
setLayout(refWoTe3.value! as any, curLayout["WoTe3"]);
|
||
setLayout(refWoTe4.value! as any, curLayout["WoTe4"]);
|
||
setLayout(refWoTe5.value! as any, curLayout["WoTe5"]);
|
||
setLayout(refWoTe6.value! as any, curLayout["WoTe6"]);
|
||
};
|
||
|
||
//位子重置
|
||
const btnLoadJson = (
|
||
distinguishValue:
|
||
| DistinguishValueInterface
|
||
| { name: string; value: number }[]
|
||
) => {
|
||
console.log("位置重置");
|
||
console.log("windowWidth.value", windowWidth.value);
|
||
console.log("windowHeight.value", windowHeight.value);
|
||
|
||
//把保存的信息放在这里
|
||
//1920 960
|
||
const dJson = {
|
||
Bar: {
|
||
left: windowWidth.value / 3.5, //432,
|
||
top: windowHeight.value / 8, //80,
|
||
width: 90, //81,
|
||
// // height: windowHeight.value/6.62,//145,
|
||
value: "0",
|
||
color: "fill-red-100",
|
||
},
|
||
};
|
||
curLayout.Bar = dJson.Bar;
|
||
console.log("dJson", dJson);
|
||
|
||
btnLoad();
|
||
};
|
||
|
||
//获取界面位置的方法
|
||
const getLayout = (refObj: any) => {
|
||
return {
|
||
left: refObj.left,
|
||
top: refObj.top,
|
||
width: refObj.width,
|
||
height: refObj.height,
|
||
value: "0",
|
||
color: "fill-red-100",
|
||
};
|
||
};
|
||
//设置界面位置
|
||
const setLayout = (refObj: any, Pos: any) => {
|
||
// console.log("d显示布局", refObj, "-------", Pos);
|
||
refObj.left = Pos.left;
|
||
refObj.top = Pos.top;
|
||
refObj.width = Pos.width;
|
||
refObj.height = Pos.height;
|
||
};
|
||
|
||
//设置文字通用颜色
|
||
const textStyle = ref("font-xs");
|
||
|
||
//设置当前的颜色分隔值
|
||
const GetColorValue = (curvalue: number) => {
|
||
// console.log(curvalue);
|
||
|
||
//先从整体里面获取总数值,然后进行开发
|
||
let arrValue: Array<{ id: string; value: any }> = new Array<{
|
||
id: string;
|
||
value: any;
|
||
}>();
|
||
arrValue.push({ id: "ChongMing", value: curLayout.ChongMing.value });
|
||
arrValue.push({ id: "PuDong", value: curLayout.PuDong.value });
|
||
arrValue.push({ id: "BaoShan", value: curLayout.BaoShan.value });
|
||
arrValue.push({ id: "JiaDing", value: curLayout.JiaDing.value });
|
||
arrValue.push({ id: "QingPu", value: curLayout.QingPu.value });
|
||
arrValue.push({ id: "JinShan", value: curLayout.JinShan.value });
|
||
arrValue.push({ id: "FengXian", value: curLayout.FengXian.value });
|
||
arrValue.push({ id: "SongJiang", value: curLayout.SongJiang.value });
|
||
arrValue.push({ id: "MinHang", value: curLayout.MinHang.value });
|
||
arrValue.push({ id: "XuHui", value: curLayout.XuHui.value });
|
||
arrValue.push({ id: "ChangNing", value: curLayout.ChangNing.value });
|
||
arrValue.push({ id: "PuTuo", value: curLayout.PuTuo.value });
|
||
arrValue.push({ id: "JingAn", value: curLayout.JingAn.value });
|
||
arrValue.push({ id: "HongKou", value: curLayout.HongKou.value });
|
||
arrValue.push({ id: "HuangPu", value: curLayout.HuangPu.value });
|
||
arrValue.push({ id: "YangPu", value: curLayout.YangPu.value });
|
||
|
||
// console.log("新生成数据值", arrValue);
|
||
|
||
//定义一个目前使用的中间值进行整体的判断操作
|
||
|
||
//下面进行改造,考虑是使用覆盖模式还是使用当前的平均值模式:
|
||
|
||
//首先要判断是不是使用均方差,是均方差,需要使用
|
||
|
||
if (basicOptions.isSqrt == true) {
|
||
// console.log("开方之前的值", curvalue);
|
||
curvalue = Math.sqrt(curvalue);
|
||
// console.log("开方之后的值", curvalue);
|
||
}
|
||
|
||
let max = 0;
|
||
let min = 60;
|
||
let intJianGe = 0;
|
||
|
||
if (basicOptions.isPresetColorRange == true) {
|
||
//就从新生成的数组里面找到位置
|
||
for (let index = 0; index <= 10; index++) {
|
||
// const element = array[index];
|
||
|
||
// console.log(
|
||
// "色彩区间",
|
||
// index,
|
||
// curvalue,
|
||
// basicOptions.colorRange[index],
|
||
// basicOptions.colorRange[index + 1]
|
||
// );
|
||
|
||
if (
|
||
curvalue > parseFloat(basicOptions.colorRange[index]) &&
|
||
curvalue <= parseFloat(basicOptions.colorRange[index + 1])
|
||
) {
|
||
return index + 1;
|
||
}
|
||
}
|
||
return 0;
|
||
} else {
|
||
// arrValue.map()
|
||
max = arrValue.reduce(function (prev, cur) {
|
||
return Math.max(prev, cur.value!);
|
||
}, 0);
|
||
// min = arrValue.reduce(function (prev, cur) {
|
||
// return Math.min(prev, cur.value!);
|
||
// }, 0);
|
||
min = arrValue.reduce((prev, cur) => Math.min(prev, cur.value), Infinity);
|
||
//最大和最小的平均分割
|
||
intJianGe = (max - min) / 4;
|
||
|
||
// console.log("计算结果", max, min, intJianGe);
|
||
|
||
//增加的间隔计算结果方法
|
||
setStepShow(min, max, intJianGe);
|
||
|
||
curMax.value = max;
|
||
|
||
for (let index = 1; index <= 9; index++) {
|
||
//const element = array[index];
|
||
if (intJianGe * index + min >= curvalue) {
|
||
return index;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
};
|
||
|
||
const changeClass = (refObj: any, index: number) => {
|
||
// console.log(index);
|
||
|
||
switch (index) {
|
||
case 1:
|
||
if (basicOptions.radioColorType == "red") refObj.value = "fill-red-400";
|
||
if (basicOptions.radioColorType == "yellow")
|
||
refObj.value = "fill-yellow-400";
|
||
if (basicOptions.radioColorType == "blue") refObj.value = "fill-blue-400";
|
||
if (basicOptions.radioColorType == "green")
|
||
refObj.value = "fill-green-400";
|
||
if (basicOptions.radioColorType == "qingxin")
|
||
refObj.value = "fill-yellow-200";
|
||
break;
|
||
case 2:
|
||
if (basicOptions.radioColorType == "red") refObj.value = "fill-red-500";
|
||
if (basicOptions.radioColorType == "yellow")
|
||
refObj.value = "fill-yellow-500";
|
||
if (basicOptions.radioColorType == "blue") refObj.value = "fill-blue-500";
|
||
if (basicOptions.radioColorType == "green")
|
||
refObj.value = "fill-green-500";
|
||
if (basicOptions.radioColorType == "qingxin")
|
||
refObj.value = "fill-green-200";
|
||
break;
|
||
case 3:
|
||
if (basicOptions.radioColorType == "red") refObj.value = "fill-red-700";
|
||
if (basicOptions.radioColorType == "yellow")
|
||
refObj.value = "fill-yellow-700";
|
||
if (basicOptions.radioColorType == "blue") refObj.value = "fill-blue-700";
|
||
if (basicOptions.radioColorType == "green")
|
||
refObj.value = "fill-green-700";
|
||
if (basicOptions.radioColorType == "qingxin")
|
||
refObj.value = "fill-sky-200";
|
||
break;
|
||
case 4:
|
||
if (basicOptions.radioColorType == "red") refObj.value = "fill-red-900";
|
||
if (basicOptions.radioColorType == "yellow")
|
||
refObj.value = "fill-yellow-900";
|
||
if (basicOptions.radioColorType == "blue") refObj.value = "fill-blue-900";
|
||
if (basicOptions.radioColorType == "green")
|
||
refObj.value = "fill-green-900";
|
||
if (basicOptions.radioColorType == "qingxin")
|
||
refObj.value = "fill-red-800";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
};
|
||
|
||
//检测覆盖设置的数据
|
||
const checkArray = () => {
|
||
var cArr = basicOptions.colorRange;
|
||
// console.log("cArr", cArr);
|
||
|
||
for (let index = 1; index < cArr.length; index++) {
|
||
// console.log("arr1,arr2", cArr[index - 1], cArr[index]);
|
||
|
||
if (parseFloat(cArr[index]) < parseFloat(cArr[index - 1])) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
|
||
//刷新页面数据
|
||
const RefreshData = () => {
|
||
///GetColor("杨浦")
|
||
// var aa=GetColorValue(curLayout.YangPu.value)
|
||
// // console.log('杨浦数据',aa);
|
||
//colorYangPu.value=aa.toString()
|
||
//colorYangPu.value="fill-red-100"
|
||
|
||
//// console.log('崇明信息',GetColorValue(curLayout.ChongMing.value));
|
||
|
||
//如果发现需要覆盖现有的参数逻辑,需要进行整个数组的叠加的增加趋势判断才行,所以需要一个函数方法;
|
||
var aa = checkArray();
|
||
if (basicOptions.isPresetColorRange == true) {
|
||
// console.log("开始识别");
|
||
if (checkArray() === false) {
|
||
ElMessage({
|
||
type: "success",
|
||
message: "覆盖的数据结构配置不正确,需要按照从小到大的状态进行设置",
|
||
});
|
||
return false;
|
||
}
|
||
}
|
||
// console.log(curLayout.ChongMing.value, "-------------------------");
|
||
|
||
changeClass(
|
||
colorChongMing,
|
||
GetColorValue(parseFloat(curLayout.ChongMing.value))
|
||
);
|
||
changeClass(colorPuDong, GetColorValue(parseFloat(curLayout.PuDong.value)));
|
||
changeClass(colorBaoShan, GetColorValue(parseFloat(curLayout.BaoShan.value)));
|
||
changeClass(colorJiaDing, GetColorValue(parseFloat(curLayout.JiaDing.value)));
|
||
changeClass(colorQingPu, GetColorValue(parseFloat(curLayout.QingPu.value)));
|
||
changeClass(colorJinShan, GetColorValue(parseFloat(curLayout.JinShan.value)));
|
||
changeClass(
|
||
colorFengXian,
|
||
GetColorValue(parseFloat(curLayout.FengXian.value))
|
||
);
|
||
changeClass(
|
||
colorSongJiang,
|
||
GetColorValue(parseFloat(curLayout.SongJiang.value))
|
||
);
|
||
changeClass(colorMinHang, GetColorValue(parseFloat(curLayout.MinHang.value)));
|
||
changeClass(colorXuHui, GetColorValue(parseFloat(curLayout.XuHui.value)));
|
||
changeClass(
|
||
colorChangNing,
|
||
GetColorValue(parseFloat(curLayout.ChangNing.value))
|
||
);
|
||
changeClass(colorPuTuo, GetColorValue(parseFloat(curLayout.PuTuo.value)));
|
||
changeClass(colorJingAn, GetColorValue(parseFloat(curLayout.JingAn.value)));
|
||
changeClass(colorHongKou, GetColorValue(parseFloat(curLayout.HongKou.value)));
|
||
changeClass(colorHuangPu, GetColorValue(parseFloat(curLayout.HuangPu.value)));
|
||
changeClass(colorYangPu, GetColorValue(parseFloat(curLayout.YangPu.value)));
|
||
|
||
const curArrayColorTemp = [];
|
||
//生成新的颜色数组
|
||
curArrayColorTemp.push({
|
||
name: "崇明",
|
||
value: curLayout.ChongMing.value,
|
||
color: colorChongMing.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "浦东",
|
||
value: curLayout.PuDong.value,
|
||
color: colorPuDong.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "宝山",
|
||
value: curLayout.BaoShan.value,
|
||
color: colorBaoShan.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "嘉定",
|
||
value: curLayout.JiaDing.value,
|
||
color: colorJiaDing.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "青浦",
|
||
value: curLayout.QingPu.value,
|
||
color: colorQingPu.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "金山",
|
||
value: curLayout.JinShan.value,
|
||
color: colorJinShan.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "奉贤",
|
||
value: curLayout.FengXian.value,
|
||
color: colorFengXian.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "松江",
|
||
value: curLayout.SongJiang.value,
|
||
color: colorSongJiang.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "闵行",
|
||
value: curLayout.MinHang.value,
|
||
color: colorMinHang.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "徐汇",
|
||
value: curLayout.XuHui.value,
|
||
color: colorXuHui.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "长宁",
|
||
value: curLayout.ChangNing.value,
|
||
color: colorChangNing.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "普陀",
|
||
value: curLayout.PuTuo.value,
|
||
color: colorPuTuo.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "静安",
|
||
value: curLayout.JingAn.value,
|
||
color: colorJingAn.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "虹口",
|
||
value: curLayout.HongKou.value,
|
||
color: colorHongKou.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "黄浦",
|
||
value: curLayout.HuangPu.value,
|
||
color: colorHuangPu.value!,
|
||
});
|
||
curArrayColorTemp.push({
|
||
name: "杨浦",
|
||
value: curLayout.YangPu.value,
|
||
color: colorYangPu.value!,
|
||
});
|
||
|
||
// streetScore
|
||
//由大到小排序
|
||
// curArrayColor.value = curArrayColorTemp.sort((a, b) => {
|
||
// if (parseFloat(a.value!) > parseFloat(b.value!)) {
|
||
// return -1;
|
||
// }
|
||
// if (parseFloat(a.value!) < parseFloat(b.value!)) {
|
||
// return 1;
|
||
// }
|
||
// return 0;
|
||
// });
|
||
curArrayColor.value = streetScore.sort((a, b) => {
|
||
if (a.value! > b.value!) {
|
||
return -1;
|
||
}
|
||
if (a.value! < b.value!) {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
});
|
||
|
||
// console.log("curArrayColor", curArrayColor.value);
|
||
};
|
||
|
||
//RefreshData();
|
||
let main1 = ref();
|
||
let main2 = ref();
|
||
let main3 = ref();
|
||
let main4 = ref();
|
||
let main5 = ref();
|
||
let main6 = ref();
|
||
let main7 = ref();
|
||
let main8 = ref();
|
||
let main9 = ref();
|
||
|
||
const relationShow = ref(false);
|
||
const isAnimating = ref(false);
|
||
|
||
let swiperRef = ref();
|
||
let timeline = ref();
|
||
let yibiao = ref();
|
||
let centerBorder = ref();
|
||
let bottomBorder = ref();
|
||
|
||
let zhifaEchartsTootipIndex = 0;
|
||
|
||
type EChartsOption = echarts.EChartsOption;
|
||
|
||
const echarts1 = () => {
|
||
var myChart = echarts.init(main1.value);
|
||
var option: EChartsOption;
|
||
|
||
option = {
|
||
title: [
|
||
{
|
||
text: "抽检监测 {score|" + checkMonitoringScore.value + "} 分",
|
||
left: "center",
|
||
right: "center",
|
||
top: "5%",
|
||
textStyle: {
|
||
color: "#00eaff", // 科技感的荧光蓝
|
||
fontSize: 18,
|
||
rich: {
|
||
score: {
|
||
fontSize: 28,
|
||
color: "#1890ff",
|
||
fontWeight: "bold",
|
||
textShadowColor: "gray", // 阴影颜色
|
||
textShadowBlur: 5, // 阴影模糊程度
|
||
textShadowOffsetX: 1, // 阴影水平偏移
|
||
textShadowOffsetY: 2, // 阴影垂直偏移
|
||
},
|
||
},
|
||
},
|
||
},
|
||
{
|
||
text: "主\n要\n问\n题",
|
||
textStyle: {
|
||
fontSize: 14,
|
||
fontWeight: "bold",
|
||
color: "#ffffff",
|
||
},
|
||
textAlign: "left",
|
||
textBaseline: "middle",
|
||
top: "50%",
|
||
},
|
||
],
|
||
|
||
tooltip: {
|
||
trigger: "item",
|
||
textStyle: {
|
||
color: "#00eaff",
|
||
},
|
||
formatter: function (params: any) {
|
||
const buhege = params.value.toFixed(1);
|
||
// 自定义 tooltip 内容
|
||
return `
|
||
<div>
|
||
<strong>${params.name}</strong><br/>
|
||
总数: ${params.data.count}<br/>
|
||
合格数: ${params.data.hege}<br/>
|
||
不合格率: ${buhege}%
|
||
</div>
|
||
`;
|
||
},
|
||
},
|
||
series: <echarts.SeriesOption>[
|
||
{
|
||
type: "wordCloud",
|
||
shape: "circle",
|
||
keepAspect: false,
|
||
// maskImage: maskImage,
|
||
left: "8%",
|
||
top: "20%",
|
||
width: "90%",
|
||
height: "75%",
|
||
right: null,
|
||
bottom: null,
|
||
sizeRange: [12, 20],
|
||
rotationRange: [0, 0],
|
||
rotationStep: 45,
|
||
gridSize: 6,
|
||
drawOutOfBound: false,
|
||
shrinkToFit: true,
|
||
layoutAnimation: true,
|
||
textStyle: {
|
||
fontFamily: "sans-serif",
|
||
fontWeight: "bold",
|
||
color: function () {
|
||
return echartsColorArray[
|
||
Math.floor(Math.random() * echartsColorArray.length)
|
||
];
|
||
},
|
||
},
|
||
emphasis: {
|
||
// focus: 'self',
|
||
textStyle: {
|
||
textShadowBlur: 3,
|
||
textShadowColor: "#333",
|
||
},
|
||
},
|
||
//data属性中的value值却大,权重就却大,展示字体就却大
|
||
data: checkMonitoringData.value,
|
||
},
|
||
],
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
|
||
myChart.setOption(option);
|
||
|
||
// 添加点击事件
|
||
myChart.on("click", function (params: any) {
|
||
console.log("点击的词云:", params.name);
|
||
defaultShow.value = true;
|
||
choujianShow.value = false;
|
||
//调用接口
|
||
setTimeout(() => {
|
||
defaultShow.value = false;
|
||
tousuShow.value = false;
|
||
zhifaShow.value = false;
|
||
choujianShow.value = true;
|
||
setTimeout(() => {
|
||
choujianEchartsPinfa();
|
||
}, 500);
|
||
}, 100);
|
||
// console.log(swiperRef.value, "swiperRef.value");
|
||
// console.log(document.getElementById("swiperBox"), "document.getElementById('swiperBox')");
|
||
setTimeout(() => {
|
||
const swiperBox = document.getElementById("swiperBox");
|
||
if (swiperBox) {
|
||
swiperBox.style.height = swiperBoxHeight.value;
|
||
}
|
||
}, 100);
|
||
});
|
||
};
|
||
|
||
const nohegelv = (hegelv: number) => {
|
||
return 100 - hegelv;
|
||
};
|
||
const echarts2 = () => {
|
||
d3.select(main2.value).html("");
|
||
// 定义一组预设的颜色
|
||
var colors = [
|
||
"RGB(0, 255, 255)",
|
||
"RGB(0, 0, 255)",
|
||
"RGB(255, 255, 0)",
|
||
"RGB(255, 192, 203)",
|
||
"RGB(255, 255, 153)",
|
||
"RGB(230, 230, 250)",
|
||
"RGB(211, 211, 211)",
|
||
];
|
||
// 创建 SVG 元素
|
||
var svg = d3
|
||
.select(main2.value)
|
||
.append("svg")
|
||
.attr("width", windowWidth.value * 0.23)
|
||
.attr("height", (windowHeight.value - 100 - 3 * 4) / 3);
|
||
|
||
// 创建布局
|
||
var layout = d3
|
||
.pack()
|
||
.size([windowWidth.value * 0.23, (windowHeight.value - 100 - 3 * 4) / 2.2])
|
||
// .size([300,300])
|
||
.padding(40);
|
||
|
||
// 数据处理
|
||
var root: any = d3
|
||
.hierarchy({ children: complaintReportData.value })
|
||
.sum(function (d: any) {
|
||
return d.value;
|
||
});
|
||
|
||
var nodes = layout(root).descendants();
|
||
|
||
// 选择Tooltip的元素
|
||
var tooltip = d3.select("#tooltip");
|
||
|
||
// 设置文字大小的比例尺
|
||
var fontSizeScale = d3
|
||
.scaleLinear()
|
||
.domain([
|
||
0,
|
||
d3.max(nodes, function (d: any) {
|
||
return d.value;
|
||
}),
|
||
])
|
||
.range([6, 28]); // 根据需要调整文字大小的范围
|
||
|
||
// 假设在y方向上我们希望缩小为原来的一半
|
||
const scaleYFactor = 0.73;
|
||
|
||
// // 遍历所有节点并应用变换
|
||
nodes.forEach((d) => {
|
||
// 更新节点的位置以模拟椭圆布局
|
||
d.y = d.y * scaleYFactor; // 缩小y坐标
|
||
|
||
// 可能还需要平移以保持在视窗内居中
|
||
// 这里的平移量取决于您的具体需求和初始SVG尺寸
|
||
// 下面只是一个例子,可能需要调整
|
||
d.y += 20;
|
||
});
|
||
// 绘制气泡图
|
||
svg
|
||
.selectAll(".node")
|
||
.data(
|
||
// nodes
|
||
nodes.filter(function (d) {
|
||
return !d.children;
|
||
})
|
||
)
|
||
.enter()
|
||
.append("circle")
|
||
.attr("class", "node")
|
||
.attr("cx", function (d) {
|
||
return d.x;
|
||
})
|
||
.attr("cy", function (d) {
|
||
return d.y;
|
||
})
|
||
.attr("r", function (d) {
|
||
return d.r;
|
||
})
|
||
.style("fill", function () {
|
||
var randomIndex = Math.floor(Math.random() * echartsColorArray.length);
|
||
return echartsColorArray[randomIndex];
|
||
})
|
||
.style("opacity", 0.7)
|
||
// 鼠标悬停事件
|
||
.on("mousemove", function (event, d: any) {
|
||
isTooltipVisible.value = true;
|
||
var name = d.data.name.length * 18;
|
||
var value = String(d.data.value.length).length * 16;
|
||
|
||
var x = event.clientX - (Number(name) + Number(value) - 50); // 获取鼠标的 x 坐标并减去tooltip的宽度,以将其定位到左侧
|
||
var y = event.clientY - 28; // 获取鼠标的 y 坐标并减去一定的值,以调整tooltip的垂直位置
|
||
tooltip.transition().duration(200).style("opacity", 0.9);
|
||
tooltip
|
||
.html(d.data.name + ":" + d.data.value)
|
||
.style("left", x + "px") // 设置 tooltip 的位置为左侧
|
||
.style("top", y + "px"); // 设置 tooltip 的垂直位置
|
||
})
|
||
// 鼠标移出事件
|
||
.on("mouseout", function () {
|
||
isTooltipVisible.value = false;
|
||
})
|
||
// 添加点击事件
|
||
.on("click", function (event, d: any) {
|
||
//右1高亮显示
|
||
console.log("点击的气泡图节点:", d.data.name);
|
||
// highlightGraphNodeByName(d.data.name);
|
||
highlightGraphNodeByName("投诉举报-销售-" + d.data.name);
|
||
|
||
// 右2显示首发,高发,频发预警
|
||
defaultShow.value = true;
|
||
choujianShow.value = true;
|
||
setTimeout(() => {
|
||
defaultShow.value = false;
|
||
choujianShow.value = false;
|
||
tousuShow.value = true;
|
||
zhifaShow.value = false;
|
||
}, 100);
|
||
|
||
setTimeout(() => {
|
||
const swiperBox = document.getElementById("swiperBox");
|
||
if (swiperBox) {
|
||
swiperBox.style.height = swiperBoxHeight.value;
|
||
}
|
||
}, 100);
|
||
});
|
||
// 添加文字标签
|
||
svg
|
||
.selectAll(".label")
|
||
.data(nodes)
|
||
.enter()
|
||
.append("text")
|
||
.attr("class", "label")
|
||
.attr("x", function (d) {
|
||
return d.x;
|
||
})
|
||
.attr("y", function (d) {
|
||
return d.y;
|
||
})
|
||
.attr("text-anchor", "middle")
|
||
.attr("dominant-baseline", "middle")
|
||
.style("font-size", function (d: any) {
|
||
return fontSizeScale(d.data.value) + "px";
|
||
})
|
||
.style("fill", "white")
|
||
.style("pointer-events", "none")
|
||
.text(function (d: any) {
|
||
return d.data.name;
|
||
});
|
||
|
||
// 创建标题元素
|
||
svg
|
||
.append("text")
|
||
.attr("class", "title")
|
||
.attr("x", 120 + (windowWidth.value * 0.23 - 246) / 2)
|
||
.attr("y", 40) // 根据需要调整标题的垂直位置
|
||
.attr("text-anchor", "middle")
|
||
.style("font-size", "18px")
|
||
.style("font-weight", "bold")
|
||
.style("fill", "#00eaff")
|
||
.text("投诉举报 ")
|
||
.append("tspan")
|
||
.attr("class", "score")
|
||
.style("font-size", "28px")
|
||
.style("font-weight", "bold")
|
||
.style("fill", "#1890ff")
|
||
.style("text-shadow", "1px 1px 2px gray") // 添加阴影效果
|
||
.text(complaintReportScore.value)
|
||
.append("tspan")
|
||
.attr("class", "unit")
|
||
.style("font-size", "22px")
|
||
.style("font-weight", "bold")
|
||
.style("fill", "#00eaff")
|
||
.text(" 分");
|
||
// 创建副标题元素
|
||
var text = ["主", "要", "问", "题"];
|
||
for (let index = 0; index < text.length; index++) {
|
||
var element = text[index];
|
||
svg
|
||
.append("text")
|
||
.attr("class", "subtitle")
|
||
.attr("x", 5) // 根据需要调整副标题的水平位置
|
||
.attr(
|
||
"y",
|
||
((windowHeight.value - 100 - 3 * 4) / 3 - 198) / 2 + 78 + 14 * index
|
||
)
|
||
// .attr("text-anchor", "middle")
|
||
.style("font-size", "14px")
|
||
.style("font-weight", "bold")
|
||
.style("fill", "#ffffff")
|
||
// .attr("transform", "rotate(90, 20, " + 300 / 2 + ")") // 将副标题旋转90度
|
||
.text(element);
|
||
}
|
||
};
|
||
const echarts3 = () => {
|
||
var myChart = echarts.init(main3.value);
|
||
var option: EChartsOption;
|
||
|
||
option = {
|
||
title: [
|
||
{
|
||
text:
|
||
"执法检查 {score|" + lawEnforcementInspectionScore.value + "} 分",
|
||
left: "center",
|
||
right: "center",
|
||
textStyle: {
|
||
color: "#00eaff",
|
||
fontSize: 18,
|
||
rich: {
|
||
score: {
|
||
fontSize: 28,
|
||
color: "#1890ff",
|
||
fontWeight: "bold",
|
||
textShadowColor: "gray", // 阴影颜色
|
||
textShadowBlur: 2, // 阴影模糊程度
|
||
textShadowOffsetX: 1, // 阴影水平偏移
|
||
textShadowOffsetY: 1, // 阴影垂直偏移
|
||
},
|
||
},
|
||
},
|
||
},
|
||
{
|
||
text: "主\n要\n问\n题",
|
||
textStyle: {
|
||
color: "#ffffff",
|
||
fontSize: 14,
|
||
fontWeight: "bold",
|
||
},
|
||
textAlign: "left",
|
||
textBaseline: "middle",
|
||
top: "50%",
|
||
},
|
||
],
|
||
label: {
|
||
show: true,
|
||
formatter: "{b} : {c}",
|
||
},
|
||
tooltip: {
|
||
show: true,
|
||
formatter: "{b} : {c}",
|
||
},
|
||
series: [
|
||
{
|
||
type: "treemap",
|
||
data: lawEnforcementInspectionData.value,
|
||
height: "70%",
|
||
breadcrumb: { show: false },
|
||
nodeClick: false
|
||
// width: "100%"
|
||
},
|
||
],
|
||
// visualMap: {
|
||
// show: false,
|
||
// inRange: {
|
||
// color: echartsColorArray,
|
||
// },
|
||
// },
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
|
||
myChart.setOption(option);
|
||
|
||
// 添加点击事件
|
||
myChart.on("click", function (params: any) {
|
||
console.log("点击的树图节点:", params.name);
|
||
highlightGraphNodeByName("执法检查-" + params.name);
|
||
// 你可以在这里根据需要进行更多操作,比如弹窗、跳转等
|
||
defaultShow.value = false;
|
||
choujianShow.value = false;
|
||
tousuShow.value = false;
|
||
zhifaShow.value = true;
|
||
setTimeout(() => {
|
||
zhifaEchartsPinfa();
|
||
}, 500)
|
||
});
|
||
};
|
||
// 初始化时间轴图表
|
||
const echarts6_old = async () => {
|
||
var myChart = echarts.init(main6.value);
|
||
var option: EChartsOption;
|
||
const timeValueMap = {
|
||
上三个月: -3,
|
||
上二个月: -2,
|
||
上一个月: -1,
|
||
当前月: 0,
|
||
下一个月: 1,
|
||
下二个月: 2,
|
||
下三个月: 3,
|
||
};
|
||
|
||
// 固化虚拟数据
|
||
|
||
// 完整数据结构
|
||
const mockDataSource = [
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "奉贤区",
|
||
month: "5", // 基准月
|
||
selectedStreet: "",
|
||
process: "",
|
||
littlemonth: 0,
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, 92, 94.8, null, null, null],
|
||
predict: [null, null, null, 94.8, 95, 96.3, 97.5],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "奉贤区",
|
||
month: "3", // 基准月
|
||
selectedStreet: "",
|
||
process: "食品安全检查",
|
||
littlemonth: 0,
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [92.6, 87.3, 93.5, 91.3, null, null, null],
|
||
predict: [null, null, null, 91.3, 92.1, 93.1, 93.3],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "奉贤区",
|
||
month: "5", // 基准月
|
||
selectedStreet: "金汇镇",
|
||
process: "食品安全检查",
|
||
littlemonth: 0,
|
||
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [89.2, 89.2, 92.3, 92.5, null, null, null],
|
||
predict: [null, null, null, 92.5, 92.7, 93.1, 93.3],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "奉贤区",
|
||
month: "5", // 基准月
|
||
selectedStreet: "金汇镇",
|
||
process: "食品安全检查",
|
||
littlemonth: -1,
|
||
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 89.2, 89.2, 92.3, null, null, null],
|
||
predict: [null, null, null, 92.3, 92.5, 93.1, 93.5],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "奉贤区",
|
||
month: "3", // 基准月
|
||
selectedStreet: "金汇镇",
|
||
process: "食品安全检查",
|
||
littlemonth: -1,
|
||
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [87.5, 87.9, 88.7, 89.2, null, null, null],
|
||
predict: [null, null, null, 89.2, 90.5, 90.9, 91.7],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "上海市",
|
||
month: "3", // 基准月
|
||
selectedStreet: "",
|
||
process: "食品安全检查",
|
||
littlemonth: -2,
|
||
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [90.8, 91.5, 91.5, 91.7, null, null, null],
|
||
predict: [null, null, null, 91.7, 92, 92.1, 92.3],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
year: 2023,
|
||
jurisdiction: "上海市",
|
||
month: "5", // 基准月
|
||
selectedStreet: "",
|
||
process: "食品安全检查",
|
||
littlemonth: -2,
|
||
|
||
timeScores: [
|
||
{
|
||
period: "上三个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 88.6, 88.7, 92.6, null, null, null],
|
||
predict: [null, null, null, 92.6, 93.1, 91.6, 90.7],
|
||
},
|
||
},
|
||
{
|
||
period: "上二个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.6, 88.7, 92.6, 87.3, null, null, null],
|
||
predict: [null, null, null, 87.3, 89.6, 91.1, 91.8],
|
||
},
|
||
},
|
||
{
|
||
period: "上一个月" as TimePeriod,
|
||
scores: {
|
||
real: [88.7, 92.6, 87.3, 93.5, null, null, null],
|
||
predict: [null, null, null, 93.5, 91.7, 92.2, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "当前月" as TimePeriod,
|
||
scores: {
|
||
real: [90.8, 91.7, 91.9, 92.2, null, null, null],
|
||
predict: [null, null, null, 92.2, 92.5, 92.9, 93.1],
|
||
},
|
||
},
|
||
{
|
||
period: "下一个月" as TimePeriod,
|
||
scores: {
|
||
real: [87.3, 93.5, 91.3, null, null, null, null],
|
||
predict: [null, null, 91.3, 92.1, 92.7, 93.1, 94.2],
|
||
},
|
||
},
|
||
{
|
||
period: "下二个月" as TimePeriod,
|
||
scores: {
|
||
real: [93.5, 91.3, null, null, null, null, null],
|
||
predict: [null, 91.3, 92.1, 92.7, 93.1, 94.2, 94],
|
||
},
|
||
},
|
||
{
|
||
period: "下三个月" as TimePeriod,
|
||
scores: {
|
||
real: [91.3, null, null, null, null, null, null],
|
||
predict: [91.3, 92.1, 92.7, 93.1, 94.2, 94, 96],
|
||
},
|
||
},
|
||
],
|
||
},
|
||
];
|
||
|
||
const mockDataSou = mockDataSource.find(
|
||
(item) =>
|
||
item.month === monthValue.value &&
|
||
item.jurisdiction === districtValue.value &&
|
||
item.selectedStreet === selectedStreet.value &&
|
||
item.littlemonth === littlemonth.value
|
||
);
|
||
// console.log('monthValue.value', monthValue.value);
|
||
// console.log('districtValue.value', districtValue.value);
|
||
// console.log('selectedStreet.value', selectedStreet.value);
|
||
// console.log('littlemonth.value', littlemonth.value);
|
||
// console.log('mockDataSou11', mockDataSou,"222",mockDataSource);
|
||
console.log("mockDataSou", mockDataSou);
|
||
const mockData = mockDataSou.timeScores.map((item) => item.scores);
|
||
console.log("mockData", mockData);
|
||
option = {
|
||
baseOption: {
|
||
timeline: {
|
||
axisType: "category",
|
||
autoPlay: true,
|
||
playInterval: 2000,
|
||
data: [
|
||
"上三个月",
|
||
"上二个月",
|
||
"上一个月",
|
||
"当前月",
|
||
"下一个月",
|
||
"下二个月",
|
||
"下三个月",
|
||
],
|
||
currentIndex: 3,
|
||
label: { formatter: (s: string) => s },
|
||
},
|
||
tooltip: {
|
||
trigger: "axis",
|
||
textStyle: {
|
||
fontSize: 10,
|
||
},
|
||
axisPointer: {
|
||
lineStyle: {
|
||
color: "#57617B",
|
||
},
|
||
},
|
||
extraCssText: "max-width: 200px; max-height: 150px; overflow-y: auto;",
|
||
},
|
||
legend: {
|
||
data: ["真实分", "预测分"],
|
||
selected: { 预测分: true, 真实分: true },
|
||
top: "30",
|
||
textStyle: {
|
||
fontSize: 10,
|
||
color: "#fff",
|
||
},
|
||
itemGap: 20,
|
||
},
|
||
calculable: true,
|
||
grid: {
|
||
top: 80,
|
||
bottom: 100,
|
||
left: "10%",
|
||
right: "5%",
|
||
},
|
||
xAxis: {
|
||
show: false, // 关键设置:隐藏X轴
|
||
type: "category",
|
||
boundaryGap: false,
|
||
data: [], // 保留空数据(或保持原有月份数据但不影响显示)
|
||
},
|
||
yAxis: {
|
||
type: "value",
|
||
min: 70,
|
||
max: 100,
|
||
interval: 5,
|
||
axisLabel: { formatter: "{value} 分" },
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,.5)",
|
||
},
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
name: "真实分",
|
||
smooth: true,
|
||
type: "line",
|
||
symbol: "circle",
|
||
symbolSize: 8,
|
||
lineStyle: { width: 2 },
|
||
color: "#5470C6",
|
||
},
|
||
{
|
||
name: "预测分",
|
||
smooth: true,
|
||
type: "line",
|
||
symbol: "circle",
|
||
symbolSize: 8,
|
||
lineStyle: {
|
||
width: 2,
|
||
type: "dashed",
|
||
},
|
||
color: "#EE6666",
|
||
},
|
||
],
|
||
},
|
||
options: mockData.map((data) => ({
|
||
series: [{ data: data.real }, { data: data.predict }],
|
||
})),
|
||
};
|
||
|
||
myChart.setOption(option);
|
||
|
||
// 保留时间轴变化监听
|
||
myChart.on("timelinechanged", (params) => {
|
||
const currentName = option.baseOption.timeline.data[params.currentIndex];
|
||
const clickValue = timeValueMap[currentName];
|
||
littlemonth.value = clickValue;
|
||
});
|
||
};
|
||
|
||
const echarts6 = () => {
|
||
var myChart = echarts.init(main6.value);
|
||
var option: EChartsOption;
|
||
|
||
option = {
|
||
title: [
|
||
{
|
||
text: "行政处罚 {score|" + istrativeSanctionScore.value + "} 分",
|
||
top: "3%",
|
||
left: "center",
|
||
right: "center",
|
||
textStyle: {
|
||
fontSize: 18,
|
||
color: "#00eaff",
|
||
rich: {
|
||
score: {
|
||
fontSize: 28,
|
||
color: "#1890ff",
|
||
fontWeight: "bold",
|
||
textShadowColor: "gray", // 阴影颜色
|
||
textShadowBlur: 2, // 阴影模糊程度
|
||
textShadowOffsetX: 1, // 阴影水平偏移
|
||
textShadowOffsetY: 1, // 阴影垂直偏移
|
||
},
|
||
},
|
||
},
|
||
},
|
||
{
|
||
text: "主\n要\n问\n题",
|
||
textStyle: {
|
||
color: "#ffffff",
|
||
fontSize: 14,
|
||
fontWeight: "bold",
|
||
},
|
||
textAlign: "left",
|
||
textBaseline: "middle",
|
||
top: "50%",
|
||
},
|
||
],
|
||
tooltip: {
|
||
trigger: "item",
|
||
formatter: "{a} <br/>{b} : {c} ({d}%)",
|
||
},
|
||
legend: {
|
||
// top: "5%",
|
||
left: "center",
|
||
bottom: "1%",
|
||
textStyle: {
|
||
color: "#00eaff",
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
name: "行政处罚种类占比",
|
||
type: "pie",
|
||
radius: ["28%", "50%"],
|
||
avoidLabelOverlap: true,
|
||
top: "-5%",
|
||
label: {
|
||
color: "#00eaff",
|
||
show: true,
|
||
formatter: "{d}%",
|
||
position: "inner",
|
||
},
|
||
minShowLabelAngle: 1,
|
||
emphasis: {
|
||
label: {
|
||
color: "#00eaff",
|
||
show: true,
|
||
fontSize: 15,
|
||
fontWeight: "bold",
|
||
},
|
||
},
|
||
labelLine: {
|
||
show: false,
|
||
},
|
||
data: istrativeSanctionData.value,
|
||
// color: echartsColorArray,
|
||
},
|
||
],
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
|
||
myChart.setOption(option);
|
||
};
|
||
|
||
const echartsYibiao = () => {
|
||
var myChart = echarts.init(yibiao.value);
|
||
var option: EChartsOption;
|
||
const szqxName = ref("上海市");
|
||
if (districtValue.value) {
|
||
szqxName.value = districtValue.value;
|
||
}
|
||
|
||
option = {
|
||
// 标题
|
||
title: [
|
||
{
|
||
left: "32%",
|
||
top: "75%",
|
||
bottom: 100,
|
||
text: szqxName.value + "综合指标",
|
||
textStyle: {
|
||
fontWeight: "bold",
|
||
fontSize: 18,
|
||
color: "#00eaff",
|
||
},
|
||
},
|
||
],
|
||
tooltip: {
|
||
show: true,
|
||
},
|
||
series: [
|
||
{
|
||
// 蓝色刻度
|
||
type: "gauge", // 图表类型为仪表盘
|
||
center: ["50%", "55%"], // 仪表盘的中心位置,默认全局居中
|
||
radius: "80%", // 仪表盘的半径大小
|
||
splitNumber: 10, // 刻度数量
|
||
min: 0, // 最小值
|
||
max: 100, // 最大值
|
||
startAngle: 200, // 起始角度
|
||
endAngle: -20, // 结束角度
|
||
clockwise: true, // 是否顺时针
|
||
axisLine: {
|
||
show: false, // 是否显示仪表盘轴线
|
||
lineStyle: {
|
||
width: 1, // 轴线宽度
|
||
shadowBlur: 0, // 轴线阴影模糊大小
|
||
color: [
|
||
[1, "#1e3a8a"], // 轴线颜色
|
||
],
|
||
},
|
||
},
|
||
axisTick: {
|
||
show: true, // 是否显示刻度
|
||
lineStyle: {
|
||
color: "#00eaff", // 刻度颜色
|
||
width: 0.5, // 刻度宽度
|
||
},
|
||
length: -5, // 刻度长度
|
||
splitNumber: 10, // 刻度分割段数
|
||
},
|
||
splitLine: {
|
||
show: true, // 是否显示分隔线
|
||
length: -8, // 分隔线长度
|
||
lineStyle: {
|
||
width: 0.8, // 刻度宽度
|
||
color: "#00eaff", // 分隔线颜色
|
||
},
|
||
},
|
||
axisLabel: {
|
||
distance: -10, // 标签与轴线的距离
|
||
color: "#00eaff", // 标签颜色
|
||
fontSize: 8, // 标签字体大小
|
||
fontWeight: "bold", // 标签字体粗细
|
||
},
|
||
pointer: {
|
||
// 仪表盘指针
|
||
show: false, // 是否显示指针
|
||
},
|
||
detail: {
|
||
show: false, // 是否显示详情
|
||
},
|
||
data: [
|
||
{
|
||
name: "", // 数据名称
|
||
value: 100, // 数据值
|
||
},
|
||
],
|
||
},
|
||
{
|
||
// 白色线条
|
||
startAngle: 200, // 仪表盘的起始角度,单位为度
|
||
endAngle: -20, // 仪表盘的结束角度,单位为度
|
||
type: "gauge", // 图表类型为仪表盘
|
||
center: ["50%", "55%"], // 仪表盘的中心位置,相对于容器的百分比
|
||
radius: "65%", // 仪表盘的半径大小,相对于容器的百分比
|
||
min: 0, // 仪表盘的最小值
|
||
max: 100, // 仪表盘的最大值
|
||
splitNumber: 0, // 刻度数量,设置为0表示不显示刻度
|
||
axisLine: {
|
||
// 坐标轴线
|
||
lineStyle: {
|
||
color: [
|
||
[0.66, "#dddddd"], // 轴线颜色的渐变,0.66处颜色为#dddddd
|
||
[1, "#dddddd"], // 轴线颜色的渐变,1处颜色为#dddddd
|
||
], // 属性lineStyle控制线条样式
|
||
width: 2, // 轴线宽度
|
||
},
|
||
},
|
||
axisLabel: {
|
||
// 坐标轴小标记
|
||
fontWeight: "bolder", // 字体粗细
|
||
fontSize: 20, // 字体大小
|
||
color: "rgba(30,144,255,0)", // 字体颜色,设置为透明
|
||
},
|
||
splitLine: {
|
||
// 分隔线
|
||
length: 10, // 分隔线长度
|
||
lineStyle: {
|
||
// 属性lineStyle(详见lineStyle)控制线条样式
|
||
width: 0, // 分隔线宽度
|
||
color: "#444", // 分隔线颜色
|
||
},
|
||
},
|
||
},
|
||
{
|
||
// 蓝色线条
|
||
startAngle: 200, // 仪表盘的起始角度,单位为度
|
||
endAngle: -20, // 仪表盘的结束角度,单位为度
|
||
type: "gauge", // 图表类型为仪表盘
|
||
center: ["50%", "55%"], // 仪表盘的中心位置,相对于容器的百分比
|
||
radius: "71%", // 仪表盘的半径大小,相对于容器的百分比
|
||
min: 0, // 仪表盘的最小值
|
||
max: 100, // 仪表盘的最大值
|
||
splitNumber: 0, // 刻度数量,设置为0表示不显示刻度
|
||
axisLine: {
|
||
// 坐标轴线
|
||
lineStyle: {
|
||
color: [
|
||
[0.66, "#1e3a8a"], // 轴线颜色的渐变,0.66处颜色为#dddddd
|
||
[1, "#1e3a8a"], // 轴线颜色的渐变,1处颜色为#dddddd
|
||
], // 属性lineStyle控制线条样式
|
||
width: 1, // 轴线宽度
|
||
},
|
||
},
|
||
axisLabel: {
|
||
// 坐标轴小标记
|
||
fontWeight: "bolder", // 字体粗细
|
||
fontSize: 16, // 字体大小
|
||
color: "rgba(30,144,255,0)", // 字体颜色,设置为透明
|
||
},
|
||
splitLine: {
|
||
// 分隔线
|
||
length: 10, // 分隔线长度
|
||
lineStyle: {
|
||
// 属性lineStyle(详见lineStyle)控制线条样式
|
||
width: 0, // 分隔线宽度
|
||
color: "#444", // 分隔线颜色
|
||
},
|
||
},
|
||
detail: {
|
||
// 详情显示
|
||
show: false, // 是否显示详情
|
||
},
|
||
},
|
||
{
|
||
// 指针和分数
|
||
name: "总分", // 图表名称
|
||
type: "gauge", // 图表类型:仪表盘
|
||
startAngle: 200, // 仪表盘的起始角度,单位为度
|
||
endAngle: -20, // 仪表盘的结束角度,单位为度
|
||
radius: "40%", // 仪表盘的半径大小,相对于容器宽度的百分比
|
||
center: ["50%", "55%"], // 仪表盘的中心位置,相对于容器的百分比,默认全局居中
|
||
min: 0, // 仪表盘的最小值
|
||
max: 100, // 仪表盘的最大值
|
||
|
||
axisLine: {
|
||
// 坐标轴线配置
|
||
show: false, // 是否显示坐标轴线
|
||
lineStyle: {
|
||
width: 25, // 坐标轴线的宽度
|
||
shadowBlur: 0, // 坐标轴线的阴影模糊程度
|
||
color: [
|
||
[0.2, "#00FAFC"], // 轴线颜色的渐变,0.2处颜色为#00FAFC(浅蓝色)
|
||
[0.4, "#3BD542"], // 轴线颜色的渐变,0.4处颜色为#3BD542(绿色)
|
||
[0.6, "#E3F424"], // 轴线颜色的渐变,0.6处颜色为#E3F424(黄色)
|
||
[0.8, "#7E48DA"], // 轴线颜色的渐变,0.8处颜色为#7E48DA(紫色)
|
||
[1, "#E531A8"], // 轴线颜色的渐变,1处颜色为#E531A8(粉红色)
|
||
],
|
||
},
|
||
},
|
||
|
||
axisTick: {
|
||
// 刻度配置
|
||
show: false, // 是否显示刻度
|
||
},
|
||
|
||
splitLine: {
|
||
// 分隔线配置
|
||
show: false, // 是否显示分隔线
|
||
},
|
||
|
||
axisLabel: {
|
||
// 坐标轴标签配置
|
||
show: false, // 是否显示坐标轴标签
|
||
},
|
||
|
||
pointer: {
|
||
// 指针配置
|
||
show: true, // 是否显示指针
|
||
width: 4, // 指针宽度
|
||
length: 50, // 指针长度
|
||
// color: '#00eaff', // 指针颜色
|
||
},
|
||
detail: {
|
||
// 详情配置
|
||
show: true, // 是否显示详情
|
||
offsetCenter: [0, "80%"], // 详情文本相对于中心点的位置偏移,x方向无偏移,y方向向下偏移80%
|
||
fontSize: 20, // 详情文本字体大小(加倍)
|
||
color: "#00eaff", // 改为白色
|
||
fontWeight: "bolder", // 加粗显示
|
||
// textShadow: '0 0 5px rgba(0, 149, 255, 0.3)', // 添加阴影使文字在透明背景上更清晰
|
||
},
|
||
itemStyle: {
|
||
// 项目样式配置
|
||
color: "#00eaff", // 项目的默认颜色
|
||
},
|
||
data: [
|
||
{
|
||
// 数据配置
|
||
value: AllCourse.value, // 当前数据值
|
||
},
|
||
],
|
||
},
|
||
],
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
|
||
myChart.setOption(option);
|
||
};
|
||
|
||
// 时间轴配置
|
||
const initTimelineChart = () => {
|
||
var myChart = echarts.init(timeline.value);
|
||
var option: EChartsOption;
|
||
const timeValueMap = {
|
||
上三个月: -3,
|
||
上二个月: -2,
|
||
上一个月: -1,
|
||
当前月: 0,
|
||
下一个月: 1,
|
||
下二个月: 2,
|
||
下三个月: 3,
|
||
// 若添加新的时间点,在此处添加对应映射
|
||
};
|
||
option = {
|
||
baseOption: {
|
||
timeline: {
|
||
axisType: "category",
|
||
autoPlay: false,
|
||
playInterval: 2000,
|
||
data: [
|
||
"上三个月",
|
||
"上二个月",
|
||
"上一个月",
|
||
"当前月",
|
||
"下一个月",
|
||
"下二个月",
|
||
"下三个月",
|
||
],
|
||
currentIndex: 3, // 默认选中第四个时间点
|
||
label: {
|
||
formatter: function (s) {
|
||
return s;
|
||
},
|
||
},
|
||
},
|
||
tooltip: {},
|
||
legend: {
|
||
left: "right",
|
||
data: [],
|
||
selected: {},
|
||
},
|
||
calculable: true,
|
||
grid: {
|
||
top: 80,
|
||
bottom: 100,
|
||
tooltip: {
|
||
trigger: "axis",
|
||
axisPointer: {
|
||
type: "shadow",
|
||
label: {
|
||
show: true,
|
||
formatter: function (params) {
|
||
return params.value.replace("\n", "");
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
series: [
|
||
// 这里可以根据实际需求添加系列
|
||
],
|
||
},
|
||
options: [
|
||
// 每个时间点对应的配置,可以根据实际需求添加
|
||
],
|
||
};
|
||
myChart.setOption(option);
|
||
|
||
// 监听时间轴的时间点变化事件
|
||
myChart.on("timelinechanged", (params) => {
|
||
const currentName = option.baseOption.timeline.data[params.currentIndex];
|
||
const clickValue = timeValueMap[currentName];
|
||
littlemonth.value = clickValue;
|
||
SelectBlur();
|
||
});
|
||
|
||
// 点击事件处理
|
||
myChart.on("click", (params: any) => { });
|
||
};
|
||
|
||
onMounted(() => {
|
||
console.log("onMounted开始执行");
|
||
|
||
getWindowWH();
|
||
getSixTableValue();
|
||
initTimelineChart();
|
||
echarts6();
|
||
initRelationshipChart();
|
||
|
||
// 获取总分数
|
||
// getAllData(
|
||
// yearValue.value,
|
||
// monthValue.value,
|
||
// stageValue.value,
|
||
// littlemonth.value
|
||
// )
|
||
getStreetAllData(
|
||
monthValue.value,
|
||
stageValue.value,
|
||
districtValue.value,
|
||
littlemonth.value
|
||
).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
// AllCourse.value = res.data.data
|
||
// .filter((item: { name: string }) => item.name === districtValue.value)[0].value;
|
||
// echartsYibiao();
|
||
if (districtValue.value == "上海市") {
|
||
// 计算所有区域的平均值
|
||
const allDistricts = res.data.data.filter((item: { name: string }) => item.name !== "上海市");
|
||
const totalValue = allDistricts.reduce((sum: number, item: { value: number }) => sum + item.value, 0);
|
||
AllCourse.value = Number((totalValue / allDistricts.length).toFixed(1));
|
||
echartsYibiao();
|
||
} else {
|
||
AllCourse.value = res.data.data.filter(
|
||
(item: { name: string }) => item.name === districtValue.value
|
||
)[0].value;
|
||
|
||
echartsYibiao();
|
||
}
|
||
console.log("AllCourse", AllCourse.value, "======================");
|
||
}
|
||
});
|
||
|
||
LoadStreetAllData();
|
||
});
|
||
|
||
const LoadStreetAllData = () => {
|
||
// 获取每个街道的分数
|
||
getStreetAllData(
|
||
monthValue.value,
|
||
stageValue.value,
|
||
districtValue.value,
|
||
littlemonth.value
|
||
).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
const courseValue = assignValuesToZonesStreet(res.data.data);
|
||
btnLoadJson(courseValue);
|
||
//刷新数据
|
||
RefreshData();
|
||
}
|
||
});
|
||
};
|
||
|
||
//加载地图列表信息,第一个网络访问方法
|
||
const lstMapLayout = ref([]);
|
||
|
||
const LoadMapLayoutList = () => {
|
||
getMapLayoutList(curId).then((res) => {
|
||
lstMapLayout.value = res.data;
|
||
// console.log("lstMapLayout", lstMapLayout);
|
||
});
|
||
};
|
||
|
||
const optMaps = ref([]);
|
||
const LoadOptMaps = () => {
|
||
loadMapOptions(curId).then((res) => {
|
||
optMaps.value = res.data.data;
|
||
// console.log("optMaps", optMaps.value);
|
||
});
|
||
};
|
||
|
||
const curSel = reactive({
|
||
name: "",
|
||
value: "",
|
||
});
|
||
|
||
//当前新增的名字
|
||
const curAddName = ref("");
|
||
|
||
//删除历史数据
|
||
const btnDelData = () => {
|
||
ElMessage({
|
||
type: "success",
|
||
message: `删除编号` + curSel.value + "的设计内容",
|
||
});
|
||
var dRet = removeMapLayout(curSel.value);
|
||
// console.log("删除返回", dRet);
|
||
//重新加载所有的信息
|
||
LoadAllDatas();
|
||
};
|
||
|
||
const LoadAllDatas = () => {
|
||
//获取当前所有的下拉菜单数据
|
||
getMapLayoutList(curId).then((res) => {
|
||
lstMapLayout.value = res.data;
|
||
// console.log("lstMapLayout", lstMapLayout);
|
||
});
|
||
//lstMapLayout.value=getMapLayoutList.data;
|
||
//获取当前所有的地图配置信息
|
||
loadMapOptions(curId).then((res) => {
|
||
optMaps.value = res.data.data;
|
||
// console.log("optMaps", optMaps.value);
|
||
});
|
||
//optMaps.value=loadMapOptions.data.data;
|
||
};
|
||
|
||
//加载当前的数据
|
||
const btnLoadData = (sel: any) => {
|
||
var dJson = JSON.parse(
|
||
(
|
||
Enumerable.from((lstMapLayout.value as any).data)
|
||
.where(function (x: any) {
|
||
return x.id == curSel.value;
|
||
})
|
||
.first() as any
|
||
).layoutdata
|
||
);
|
||
|
||
basicOptions.backgroundColor = dJson.Options.backgroundColor;
|
||
basicOptions.barTextColor = dJson.Options.barTextColor;
|
||
basicOptions.barTitle = dJson.Options.barTitle;
|
||
basicOptions.colorRange = dJson.Options.colorRange;
|
||
basicOptions.isPresetColorRange = dJson.Options.isPresetColorRange;
|
||
basicOptions.isSqrt = dJson.Options.isSqrt;
|
||
basicOptions.radioColorType = dJson.Options.radioColorType;
|
||
|
||
curLayout.ChongMing = dJson.ChongMing;
|
||
curLayout.PuDong = dJson.PuDong;
|
||
curLayout.BaoShan = dJson.BaoShan;
|
||
curLayout.JiaDing = dJson.JiaDing;
|
||
curLayout.QingPu = dJson.QingPu;
|
||
curLayout.JinShan = dJson.JinShan;
|
||
curLayout.FengXian = dJson.FengXian;
|
||
curLayout.SongJiang = dJson.SongJiang;
|
||
curLayout.MinHang = dJson.MinHang;
|
||
curLayout.XuHui = dJson.XuHui;
|
||
curLayout.ChangNing = dJson.ChangNing;
|
||
curLayout.PuTuo = dJson.PuTuo;
|
||
curLayout.JingAn = dJson.JingAn;
|
||
curLayout.HongKou = dJson.HongKou;
|
||
curLayout.HuangPu = dJson.HuangPu;
|
||
curLayout.YangPu = dJson.YangPu;
|
||
curLayout.Bar = dJson.Bar;
|
||
|
||
// console.log("柱状图", dJson.Bar);
|
||
btnLoad();
|
||
};
|
||
|
||
//获取浏览器可视化页面的宽高
|
||
const getWindowWH = () => {
|
||
//本地浏览器可视长宽:1920*960
|
||
// console.log("浏览器宽度", window.innerWidth);
|
||
// console.log("浏览器高度", window.innerHeight);
|
||
windowHeight.value = window.innerHeight;
|
||
windowWidth.value = window.innerWidth;
|
||
// // console.log((windowHeight.value - 62 - 3 * 4) / 3 + 2 * 4, "-------------------------");
|
||
|
||
// 设置上下两个盒子间隙
|
||
const topBottomGap = 10;
|
||
//顶部空隙
|
||
const topGap = 52;
|
||
// 底部空隙
|
||
const bottomGap = 15;
|
||
// 左右空隙
|
||
const leftRightGap = 100;
|
||
// 最外层左右空隙
|
||
const leftRightGap1 = 20;
|
||
//单个盒子的高度
|
||
const mainHeight =
|
||
(windowHeight.value - 2 * topBottomGap - topGap - bottomGap) / 3;
|
||
// 单个盒子的宽度
|
||
const mainWidth = windowWidth.value * 0.25;
|
||
// 中间盒子的宽度
|
||
const centerWidth =
|
||
windowWidth.value - 2 * (leftRightGap1 + mainWidth + leftRightGap);
|
||
|
||
main1.value.style.left = leftRightGap1 + "px";
|
||
main1.value.style.width = mainWidth + "px";
|
||
main1.value.style.height = mainHeight + "px";
|
||
main1.value.style.top = 0 + "px";
|
||
|
||
main2.value.style.left = leftRightGap1 + "px";
|
||
main2.value.style.position = "absolute";
|
||
main2.value.style.width = mainWidth + "px";
|
||
main2.value.style.height = mainHeight + "px";
|
||
main2.value.style.top = mainHeight + topBottomGap + "px";
|
||
|
||
main3.value.style.left = leftRightGap1 + "px";
|
||
main3.value.style.width = mainWidth + "px";
|
||
main3.value.style.height = mainHeight + "px";
|
||
main3.value.style.top = 2 * mainHeight + 2 * topBottomGap + "px";
|
||
|
||
main4.value.style.left = windowWidth.value - mainWidth - leftRightGap1 + "px";
|
||
main4.value.style.position = 'absolute';
|
||
main4.value.style.width = mainWidth + "px";
|
||
main4.value.style.height = 0.4 * mainHeight + "px";
|
||
main4.value.style.top = 0 + "px";
|
||
|
||
main5.value.style.left = windowWidth.value - mainWidth - leftRightGap1 + "px";
|
||
main5.value.style.position = "absolute";
|
||
main5.value.style.width = mainWidth + "px";
|
||
main5.value.style.height = 1.6 * mainHeight + "px";
|
||
main5.value.style.top = 0.4 * mainHeight + topBottomGap + "px";
|
||
swiperBoxHeight.value = main5.value.style.height;
|
||
|
||
main6.value.style.left = windowWidth.value - mainWidth - leftRightGap1 + "px";
|
||
main6.value.style.width = mainWidth + "px";
|
||
main6.value.style.height = mainHeight + "px";
|
||
main6.value.style.top = main3.value.style.top;
|
||
|
||
main9.value.style.left = main6.value.style.left;
|
||
main9.value.style.width = main6.value.style.width;
|
||
main9.value.style.height = main6.value.style.height;
|
||
main9.value.style.top = main6.value.style.top;
|
||
|
||
// centerBorder.value.style.width = centerWidth + "px";
|
||
// centerBorder.value.style.height = windowHeight.value * 0.7 + "px";
|
||
// centerBorder.value.style.left = windowWidth.value * 0.5 + "px";
|
||
// centerBorder.value.style.top = windowHeight.value * 0.5 + "px";
|
||
// centerBorder.value.style.transform = "translate(-50%, -50%)";
|
||
|
||
timeline.value.style.width = windowWidth.value * 0.47 + "px";
|
||
};
|
||
|
||
//获取六个表的值+获取二级指标的值
|
||
const getSixTableValue = () => {
|
||
//抽检监测表格(1表)
|
||
getCheckMonitoringValueStreet(
|
||
monthValue.value,
|
||
stageValue.value,
|
||
districtValue.value,
|
||
selectedStreet.value,
|
||
littlemonth.value
|
||
).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
checkMonitoringScore.value = res.data.score;
|
||
checkMonitoringData.value = res.data.data.map(
|
||
(item: {
|
||
zongjianshu: any;
|
||
hegejianshu: any;
|
||
sp_dl: string;
|
||
hegelv: number;
|
||
}) => ({
|
||
name: item.sp_dl,
|
||
value: nohegelv(item.hegelv),
|
||
hege: item.hegejianshu,
|
||
count: item.zongjianshu,
|
||
})
|
||
);
|
||
echarts1();
|
||
}
|
||
});
|
||
|
||
// //投诉举报表格(2表)
|
||
getComplaintReportValueStreet(
|
||
monthValue.value,
|
||
stageValue.value,
|
||
districtValue.value,
|
||
selectedStreet.value,
|
||
littlemonth.value
|
||
).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
complaintReportScore.value = res.data.score;
|
||
complaintReportData.value = res.data.data.map(
|
||
(item: { tousuqingxin: string; tousushu: number }) => ({
|
||
name: item.tousuqingxin,
|
||
value: item.tousushu,
|
||
})
|
||
);
|
||
echarts2();
|
||
}
|
||
});
|
||
//执法检查表格(3表)
|
||
getLawEnforcementInspectionValueStreet(
|
||
monthValue.value,
|
||
stageValue.value,
|
||
districtValue.value,
|
||
selectedStreet.value,
|
||
littlemonth.value
|
||
).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
lawEnforcementInspectionScore.value = res.data.score;
|
||
lawEnforcementInspectionData.value = res.data.data.map(
|
||
(item: { wentiqingxin: string; wentishu: number }) => ({
|
||
name: item.wentiqingxin,
|
||
value: item.wentishu,
|
||
})
|
||
);
|
||
echarts3();
|
||
}
|
||
});
|
||
|
||
//行政处罚表格(6表)
|
||
getIstrativeSanctionValueStreet(monthValue.value, stageValue.value, districtValue.value, selectedStreet.value, littlemonth.value).then(
|
||
(res) => {
|
||
if (res.data.msg == "success") {
|
||
istrativeSanctionScore.value = res.data.score;
|
||
istrativeSanctionData.value = res.data.data.map(
|
||
(item: { chufaqinxing: string; chufaqiye: number }) => ({
|
||
name: item.chufaqinxing,
|
||
value: item.chufaqiye,
|
||
})
|
||
);
|
||
echarts6();
|
||
}
|
||
}
|
||
);
|
||
|
||
// 获取二级指标的值
|
||
getSecondLevelMetricValues(districtValue.value).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
for (let index = 0; index < res.data.data.length; index++) {
|
||
const element = res.data.data[index];
|
||
switch (element.zb) {
|
||
case "市民满意度":
|
||
SecondLevelMetricValues.value.citizenSatisfaction = element.score;
|
||
break;
|
||
case "市民知晓度":
|
||
SecondLevelMetricValues.value.citizenAwareness = element.score;
|
||
break;
|
||
case "食物中毒发生率":
|
||
SecondLevelMetricValues.value.foodPoisoningIncidence = element.score;
|
||
break;
|
||
case "企业管理体系认证率":
|
||
SecondLevelMetricValues.value.certificationRate = element.score;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
//将各个区的分数赋到对应的变量上
|
||
const assignValuesToZones = (courseValue: any[]) => {
|
||
const a: DistinguishValueInterface = {};
|
||
|
||
for (let index = 0; index < courseValue.length; index++) {
|
||
const name = courseValue[index].name;
|
||
const course: any = courseValue[index].score;
|
||
switch (name) {
|
||
case "崇明区":
|
||
a.ChongMing = course;
|
||
break;
|
||
case "浦东新区":
|
||
a.PuDong = course;
|
||
break;
|
||
case "宝山区":
|
||
a.BaoShan = course;
|
||
break;
|
||
case "嘉定区":
|
||
a.JiaDing = course;
|
||
break;
|
||
case "青浦区":
|
||
a.QingPu = course;
|
||
break;
|
||
case "金山区":
|
||
a.JinShan = course;
|
||
break;
|
||
case "奉贤区":
|
||
a.FengXian = course;
|
||
break;
|
||
case "松江区":
|
||
a.SongJiang = course;
|
||
break;
|
||
case "闵行区":
|
||
a.MinHang = course;
|
||
break;
|
||
case "徐汇区":
|
||
a.XuHui = course;
|
||
break;
|
||
case "长宁区":
|
||
a.ChangNing = course;
|
||
break;
|
||
case "普陀区":
|
||
a.PuTuo = course;
|
||
break;
|
||
case "静安区":
|
||
a.JingAn = course;
|
||
break;
|
||
case "虹口区":
|
||
a.HongKou = course;
|
||
break;
|
||
case "黄浦区":
|
||
a.HuangPu = course;
|
||
break;
|
||
case "杨浦区":
|
||
a.YangPu = course;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return a;
|
||
};
|
||
|
||
// 离开焦点触发
|
||
const SelectBlur = () => {
|
||
getSixTableValue();
|
||
echarts6();
|
||
// 获取总分数
|
||
// getAllData(
|
||
// yearValue.value,
|
||
// monthValue.value,
|
||
// stageValue.value,
|
||
// littlemonth.value
|
||
// )
|
||
getStreetAllData(
|
||
monthValue.value,
|
||
stageValue.value,
|
||
districtValue.value,
|
||
littlemonth.value
|
||
).then((res) => {
|
||
if (res.data.msg == "success") {
|
||
if (districtValue.value == "上海市") {
|
||
// 计算所有区域的平均值
|
||
const allDistricts = res.data.data.filter((item: { name: string }) => item.name !== "上海市");
|
||
const totalValue = allDistricts.reduce((sum: number, item: { value: number }) => sum + item.value, 0);
|
||
AllCourse.value = Number((totalValue / allDistricts.length).toFixed(1));
|
||
echartsYibiao();
|
||
} else {
|
||
AllCourse.value = res.data.data.filter(
|
||
(item: { name: string }) => item.name === districtValue.value
|
||
)[0].value;
|
||
|
||
echartsYibiao();
|
||
}
|
||
console.log("AllCourse", AllCourse.value, "======================");
|
||
}
|
||
});
|
||
|
||
LoadStreetAllData();
|
||
};
|
||
|
||
//获取cookie
|
||
const getCookie = () => {
|
||
let reg = RegExp("Admin-Token" + "=([^;]+)");
|
||
let arr = document.cookie.match(reg);
|
||
if (arr) {
|
||
return arr[1];
|
||
} else {
|
||
return "没有获取到该cookie";
|
||
}
|
||
};
|
||
|
||
const getRandomNumber = (min: number, max: number) => {
|
||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||
};
|
||
|
||
// 设置白鸽位置
|
||
const setDovePositon = () => {
|
||
debugger;
|
||
const containerTitle = document.getElementById("containerTitle");
|
||
const doveNumbers = getRandomNumber(5, 8);
|
||
for (let index = 0; index < doveNumbers; index++) {
|
||
const dove = document.createElement("img");
|
||
dove.src = "/public/image/dove.png";
|
||
dove.classList.add("dove");
|
||
dove.style.left =
|
||
getRandomNumber(window.innerWidth * 0.15, window.innerWidth * 0.85) +
|
||
"px";
|
||
dove.style.top = getRandomNumber(0, 52) + "px";
|
||
dove.style.width = getRandomNumber(64, 128) + "px";
|
||
containerTitle?.appendChild(dove);
|
||
}
|
||
};
|
||
|
||
interface ScoreInterval {
|
||
min: number;
|
||
max: number;
|
||
color: string;
|
||
}
|
||
// 定义区间
|
||
let scoreIntervals: ScoreInterval[] = [
|
||
{ min: 0, max: 24, color: "#60a5fa" },
|
||
{ min: 25, max: 50, color: "#3b82f6" },
|
||
{ min: 51, max: 75, color: "#1d4ed8" },
|
||
{ min: 75, max: 100, color: "#1e3a8a" },
|
||
];
|
||
|
||
interface AllScoreVO {
|
||
name: string;
|
||
street: string;
|
||
value: number;
|
||
xzcf: number;
|
||
xxzs: number;
|
||
tsjb: number;
|
||
zfjc: number;
|
||
cckh: number;
|
||
cjjc: number;
|
||
zhx: number;
|
||
score: number;
|
||
weight_add: number;
|
||
}
|
||
|
||
//街道成绩
|
||
// let streetScore = [
|
||
// { name: '海湾镇', value: 38 },
|
||
// { name: '金汇镇', value: 90 },
|
||
// { name: '庄行镇', value: 90 },
|
||
// { name: '上海市奉贤区海湾旅游区', value: 90 },
|
||
// { name: '青村镇', value: 90 },
|
||
// { name: '西渡街道', value: 90 },
|
||
// { name: '四团镇', value: 90 },
|
||
// { name: '金海街道', value: 90 },
|
||
// { name: '奉浦街道', value: 90 },
|
||
// { name: '奉城镇', value: 90 },
|
||
// { name: '柘林镇', value: 90 },
|
||
// { name: '上海海港综合经济开发区', value: 90 },
|
||
// { name: '南桥镇', value: 90 }
|
||
// // 省略其他数据
|
||
// ];
|
||
|
||
//街道成绩
|
||
let streetScore = [
|
||
{ name: "华阳路街道", value: 38 },
|
||
{ name: "金汇镇", value: 90 },
|
||
{ name: "程家桥街道", value: 90 },
|
||
{ name: "新泾镇", value: 90 },
|
||
{ name: "新华路街道", value: 90 },
|
||
{ name: "北新泾街道", value: 90 },
|
||
{ name: "江苏路街道", value: 90 },
|
||
{ name: "周家桥街道", value: 90 },
|
||
{ name: "天山路街道", value: 90 },
|
||
{ name: "仙霞新村街道", value: 90 },
|
||
// 省略其他数据
|
||
];
|
||
|
||
//街道成绩赋值
|
||
const assignValuesToZonesStreet = (streetScoreVO: AllScoreVO[]) => {
|
||
const result: DistinguishValueInterface = {};
|
||
|
||
//将结果保存到街道成绩中
|
||
console.log("streetScoreVO00000000000000", streetScoreVO);
|
||
if (districtValue.value == "上海市") {
|
||
streetScore = streetScoreVO.map((item) => {
|
||
result[item.name] = item.value;
|
||
return {
|
||
name: item.name,
|
||
value: item.value,
|
||
};
|
||
});
|
||
} else {
|
||
streetScore = streetScoreVO.map((item) => {
|
||
result[item.street] = item.value;
|
||
return {
|
||
name: item.street,
|
||
value: item.value,
|
||
};
|
||
});
|
||
}
|
||
|
||
// 对 streetScore 进行从大到小排序
|
||
streetScore = streetScore.sort((a, b) => a.value - b.value);
|
||
|
||
//设定四个区间
|
||
// // 计算最大值和最小值
|
||
const maxScore = Math.max(...streetScore.map((item) => item.value));
|
||
const minScore = Math.min(...streetScore.map((item) => item.value));
|
||
|
||
// 计算区间
|
||
const interval = (maxScore - minScore) / 4;
|
||
|
||
// 定义区间
|
||
scoreIntervals = [
|
||
{ min: minScore, max: minScore + interval, color: "#60a5fa" },
|
||
{
|
||
min: minScore + interval + 0.01,
|
||
max: minScore + 2 * interval,
|
||
color: "#3b82f6",
|
||
},
|
||
{
|
||
min: minScore + 2 * interval + 0.01,
|
||
max: minScore + 3 * interval,
|
||
color: "#1d4ed8",
|
||
},
|
||
{ min: minScore + 3 * interval + 0.01, max: maxScore, color: "#1e3a8a" },
|
||
];
|
||
|
||
initStreetChart();
|
||
|
||
return streetScore;
|
||
};
|
||
|
||
const selectedStreet = ref<string>("");
|
||
|
||
// 初始化街道地图
|
||
// aaaaaaaaaaaaaaaaaa
|
||
const initStreetChart = () => {
|
||
// 先获取之前的 ECharts 实例并销毁
|
||
const streetMapElement = document.getElementById(
|
||
"streetMapEcharts"
|
||
) as HTMLElement;
|
||
const existingChart = echarts.getInstanceByDom(streetMapElement);
|
||
if (existingChart) {
|
||
existingChart.dispose();
|
||
}
|
||
shangHaiJieDao as GeoJSONSourceInput;
|
||
shangHaiXiaQu as GeoJSONSourceInput;
|
||
// console.log('shangHaiJieDao', shangHaiJieDao);
|
||
|
||
// 过滤 geoJson 数组,只保留当前请求的街道
|
||
|
||
//根据请求结果包含的街道决定显示的街道
|
||
//拿出请求结果包含全部街道的名字
|
||
const streetNames = streetScore.map((item) => item.name);
|
||
|
||
//根据请求结果包含的街道决定显示的街道
|
||
let filteredFeatures;
|
||
if (districtValue.value == "上海市") {
|
||
// console.log('streetNames111111111', streetNames);
|
||
filteredFeatures = shangHaiXiaQu.features
|
||
.filter((feature: any) => streetNames.includes(feature.properties.name))
|
||
.map((feature: any) => ({ ...feature, type: "Feature" }));
|
||
// console.log('filteredFeatures1111111111', filteredFeatures);
|
||
} else {
|
||
// console.log('streetNames22222222222222', streetNames);
|
||
filteredFeatures = shangHaiJieDao.features
|
||
.filter((feature: any) => streetNames.includes(feature.properties.name))
|
||
.map((feature: any) => ({ ...feature, type: "Feature" }));
|
||
// console.log('filteredFeatures2222222222222', filteredFeatures);
|
||
}
|
||
|
||
// 创建新的 GeoJSONSourceInput 对象
|
||
const nowGeoJson: GeoJSONSourceInput = {
|
||
type: "FeatureCollection",
|
||
features: filteredFeatures,
|
||
};
|
||
|
||
// 注册地图
|
||
echarts.registerMap("JiedaoMap", nowGeoJson);
|
||
// 初始化地图
|
||
const streetChart = echarts.init(
|
||
document.getElementById("streetMapEcharts") as HTMLElement
|
||
);
|
||
|
||
console.log("streetScore", streetScore);
|
||
|
||
const streetOption = {
|
||
//网格布局
|
||
grid: {
|
||
right: "100%",
|
||
top: "10%",
|
||
// bottom: "10%",
|
||
width: "20%",
|
||
left: "12%", // 调整此属性以向右移动柱状图
|
||
},
|
||
//区间分数
|
||
visualMap: {
|
||
pieces: scoreIntervals.map((interval) => ({
|
||
gte: parseFloat(interval.min.toFixed(1)),
|
||
lte: parseFloat(interval.max.toFixed(1)),
|
||
color: interval.color,
|
||
})),
|
||
show: true, // 视觉映射控件
|
||
//定位区间
|
||
left: "83%", // 距离容器左侧 10%
|
||
top: "5%", // 垂直居中
|
||
orient: "vertical", // 垂直方向
|
||
textStyle: {
|
||
color: "#dbeafe",
|
||
fontSize: 12, // 设置字体大小
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
type: "map", // 图表类型为地图
|
||
map: "JiedaoMap", // 使用注册的地图名称
|
||
geoIndex: 10, // 地理坐标系组件的索引
|
||
zoom: districtValue.value === "上海市" ? 1.2 : 0.9, // 地图缩放等级
|
||
// left: '18%', // 距离左侧10%
|
||
// top: '15%', //
|
||
left: "center",
|
||
top: districtValue.value === "上海市" ? "12%" : "15%",
|
||
right: "auto",
|
||
bottom: "auto",
|
||
// center: [121.52, 30.94],
|
||
showLegendSymbol: false, // 不显示图例标记
|
||
label: {
|
||
normal: {
|
||
show: true, // 正常状态下显示标签
|
||
formatter: function (params: { name: any; data: { value: any } }) {
|
||
const name = params.name;
|
||
const value = params.data ? params.data.value : "";
|
||
return `${name}\n${value}`;
|
||
},
|
||
textStyle: {
|
||
color: "#fff", // 标签文字颜色
|
||
fontSize: 11, // 标签文字大小
|
||
},
|
||
},
|
||
emphasis: {
|
||
show: true,
|
||
textStyle: { color: "#fff" },
|
||
}, // 高亮状态下不显示标签,文本颜色为白色
|
||
},
|
||
roam: false, // 关闭鼠标缩放和平移漫游
|
||
itemStyle: {
|
||
normal: { areaColor: "#031525", borderColor: "#FFFFFF" }, // 正常状态下区域颜色和边界颜色
|
||
emphasis: { areaColor: "#2B91B7" }, // 高亮状态下区域颜色
|
||
},
|
||
animation: false, // 关闭动画
|
||
data: streetScore, // 地图数据
|
||
},
|
||
{
|
||
type: "bar",
|
||
data: streetScore.map((item) => 0),
|
||
barWidth: 10, // 设置柱子最大宽度为10px
|
||
barMaxWidth: 0, // 设置柱子最大宽度为0
|
||
barMinWidth: 0, // 设置柱子最小宽度为0
|
||
// 隐藏柱子核心配置
|
||
itemStyle: {
|
||
show: false,
|
||
color: "#dbeafe", //
|
||
borderColor: "transparent", // 同步隐藏边框
|
||
},
|
||
label: {
|
||
show: false,
|
||
position: "right",
|
||
color: "#dbeafe",
|
||
fontSize: 15,
|
||
distance: 10,
|
||
formatter: (params: { dataIndex: number }) =>
|
||
streetScore[params.dataIndex].value,
|
||
// 关键修复:强制标签显示
|
||
overflow: "truncate", // 文本溢出处理
|
||
// height: 50, // 设置标签最大高度
|
||
width: 50, // 设置标签最大宽度
|
||
align: "left", // 左对齐保证位置
|
||
},
|
||
},
|
||
],
|
||
xAxis: {
|
||
type: "value",
|
||
position: "top",
|
||
show: false,
|
||
// splitLine: { show: false },
|
||
// axisLabel: { show: false },
|
||
// axisLine: { show: false },
|
||
// axisTick: { show: false }
|
||
},
|
||
yAxis: {
|
||
show: false,
|
||
type: "category",
|
||
data: streetScore.map((item) => item.name),
|
||
axisLabel: {
|
||
color: "#dbeafe", // 设置统一的颜色
|
||
formatter: function (value: string) {
|
||
if (value === "上海市奉贤区海湾旅游区") {
|
||
return "上海...旅游区";
|
||
} else if (value === "上海海港综合经济开发区") {
|
||
return "上海...开发区";
|
||
}
|
||
return value;
|
||
},
|
||
},
|
||
boundaryGap: true,
|
||
axisLine: { show: true },
|
||
axisTick: { show: true },
|
||
},
|
||
};
|
||
|
||
streetChart.setOption(streetOption);
|
||
|
||
// 监听点击事件
|
||
streetChart.on("click", function (params) {
|
||
if (
|
||
params.componentType === "series" &&
|
||
params.seriesType === "map" &&
|
||
selectedStreet.value !== params.name
|
||
) {
|
||
selectedStreet.value = params.name; // 设置选中的区域名称
|
||
getSixTableValue();
|
||
console.log("点击的区域:", params.name);
|
||
console.log("点击的区域数据:", params.data);
|
||
// 在这里可以添加更多的逻辑来处理高亮区域
|
||
} else if (
|
||
params.componentType === "series" &&
|
||
params.seriesType === "map" &&
|
||
selectedStreet.value == params.name
|
||
) {
|
||
//重复点击某个区块(街道)
|
||
streetChart.dispatchAction({
|
||
type: "unselect",
|
||
name: params.name,
|
||
});
|
||
//对街道条件置空
|
||
selectedStreet.value = "";
|
||
getSixTableValue();
|
||
console.log("点击的区域:", params.name);
|
||
console.log("点击的区域数据:", params.data);
|
||
// 在这里可以添加更多的逻辑来处理高亮区域
|
||
}
|
||
echarts6();
|
||
});
|
||
};
|
||
|
||
// 新增初始化方法
|
||
const initRelationshipChart = () => {
|
||
// return;
|
||
const chartDom = main9.value;
|
||
if (!chartDom) return;
|
||
|
||
chartRelationship = echarts.init(chartDom);
|
||
|
||
getRelationshipNetwork().then((res) => {
|
||
// 处理节点数据,为每个节点设置初始样式
|
||
const nodes = res.data.nodes.map((node: any) => ({
|
||
...node,
|
||
symbolSize: 10, // 节点大小
|
||
value: 15, // 节点权重(可用于布局)
|
||
draggable: false, // 节点不可拖动
|
||
itemStyle: {
|
||
opacity: 0.8, // 节点初始透明度
|
||
},
|
||
}));
|
||
|
||
// 处理连线数据,为每条连线设置初始样式
|
||
const links = res.data.links.map((link: any) => ({
|
||
...link,
|
||
lineStyle: {
|
||
opacity: 0.3, // 连线初始透明度
|
||
},
|
||
}));
|
||
|
||
// ECharts 配置项
|
||
const option: echarts.EChartsOption = {
|
||
title: {
|
||
text: "食品安全综合指数重点指标关联网络", // 图表标题
|
||
textStyle: {
|
||
color: "#81E7ED", // 标题颜色
|
||
fontSize: 15, // 标题字体大小
|
||
fontWeight: "bold", // 标题加粗
|
||
},
|
||
},
|
||
tooltip: {
|
||
trigger: "item", // 悬停显示节点或连线信息
|
||
textStyle: { fontSize: 10 },
|
||
},
|
||
animationDuration: 0, // 初始动画时长
|
||
// animationEasingUpdate: 'quinticInOut', // 更新动画缓动效果
|
||
animationEasingUpdate: "linear", // 更新动画缓动效果
|
||
series: [
|
||
{
|
||
type: "graph", // 图类型为关系图
|
||
layout: "force", // 使用力引导布局
|
||
zoom: 0.8,
|
||
force: {
|
||
repulsion: 1000, // 节点之间的斥力
|
||
edgeLength: 1000, // 边的长度
|
||
gravity: 10, // 重力系数
|
||
},
|
||
emphasis: {
|
||
// 鼠标悬停或高亮时的样式
|
||
focus: "adjacency", // 高亮与当前节点相邻的节点和连线
|
||
label: {
|
||
show: true,
|
||
color: "#fff",
|
||
fontSize: 12,
|
||
},
|
||
lineStyle: {
|
||
width: 2,
|
||
color: "#ffeb7b",
|
||
},
|
||
},
|
||
select: {
|
||
// 选中节点时的样式
|
||
itemStyle: {
|
||
borderColor: "#fff",
|
||
borderWidth: 2,
|
||
},
|
||
},
|
||
data: nodes, // 节点数据
|
||
links: links, // 连线数据
|
||
categories: res.data.categories, // 节点分类(用于分组着色等)
|
||
roam: true, // 支持鼠标缩放和平移
|
||
label: {
|
||
show: true, // 显示节点标签
|
||
position: "top", // 标签显示在节点上方
|
||
textBorderColor: "#fff", // 标签描边色
|
||
color: "#fff", // 标签字体颜色
|
||
},
|
||
lineStyle: {
|
||
color: "source", // 连线颜色跟随源节点
|
||
curveness: 0, // 连线弯曲度
|
||
type: "solid", // 连线为实线
|
||
},
|
||
},
|
||
],
|
||
};
|
||
|
||
// 渲染图表
|
||
chartRelationship.setOption(option);
|
||
});
|
||
|
||
// 窗口变化时自适应
|
||
// window.addEventListener('resize', () => chartRelationship.resize());
|
||
};
|
||
|
||
// 在组件卸载时清理
|
||
onBeforeUnmount(() => {
|
||
if (chartRelationship) {
|
||
chartRelationship.dispose();
|
||
window.removeEventListener("resize", () => chartRelationship?.resize());
|
||
}
|
||
});
|
||
|
||
// 添加滚动数据
|
||
|
||
const scrollData = ref([
|
||
{
|
||
xiangmu: "霉菌",
|
||
xiaolei: "代用茶",
|
||
danwei: "上海新欧尚超市有限公司嘉定店",
|
||
time: "2023-04-11",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "鳜鱼",
|
||
danwei: "上海盒马网络科技有限公司长宁第三分公司",
|
||
time: "2023-04-25",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "氯氟氰菊酯和高效氯氟氰菊酯",
|
||
xiaolei: "芹菜",
|
||
danwei: "上海市奉贤区孙超农产品经营部",
|
||
time: "2023-04-17",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "亚硝酸盐(以亚硝酸钠计)",
|
||
xiaolei: "熏煮香肠火腿制品",
|
||
danwei: "上海盒马网络科技有限公司宝山第二分公司",
|
||
time: "2023-04-07",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "呋喃唑酮代谢物",
|
||
xiaolei: "鸡肉",
|
||
danwei: "上海市松江区新桥镇东虎饮食店",
|
||
time: "2023-04-28",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "氯氟氰菊酯和高效氯氟氰菊酯",
|
||
xiaolei: "姜",
|
||
danwei: "上海申捷餐饮有限公司",
|
||
time: "2023-04-20",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "啶虫脒",
|
||
xiaolei: "豇豆",
|
||
danwei: "上海市闵行区美佳要超市",
|
||
time: "2023-04-24",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "防腐剂混合使用时各自用量占其最大使用量的比例之和",
|
||
xiaolei: "酱卤肉制品",
|
||
danwei: "上海普陀盒马互联网网络科技有限公司",
|
||
time: "2023-04-13",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "环丙氨嗪",
|
||
xiaolei: "鸡肉",
|
||
danwei: "上海优加超市有限公司",
|
||
time: "2023-04-25",
|
||
dengji: "red",
|
||
},
|
||
]);
|
||
|
||
const choujianShoufaData = ref([
|
||
{
|
||
xiangmu: "氯霉素",
|
||
xiaolei: "蛏",
|
||
danwei: "上海农产品中心批发市场经营管理有限公司潘光剑",
|
||
time: "2023-04-28",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "鳜鱼",
|
||
danwei: "上海盒马网络科技有限公司长宁第三分公司",
|
||
time: "2023-04-25",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "呋喃唑酮代谢物",
|
||
xiaolei: "基围虾(海水虾)",
|
||
danwei: "沪陵农贸市场 褚衍涛",
|
||
time: "2023-04-17",
|
||
dengji: "orange",
|
||
},
|
||
{
|
||
xiangmu: "呋喃唑酮代谢物",
|
||
xiaolei: "南美白对虾",
|
||
danwei: "上海普陀盒马互联网络科技有限公司",
|
||
time: "2023-04-13",
|
||
dengji: "orange",
|
||
},
|
||
]);
|
||
|
||
const choujianGaofaData = ref([
|
||
// 第一张图片中的水产品数据
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "鳊鱼",
|
||
choujian: 63,
|
||
buhegelv: 30.2,
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "泥鳅",
|
||
choujian: 9,
|
||
buhegelv: 77.8,
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "草虾(淡水虾)",
|
||
choujian: 2,
|
||
buhegelv: 50.0,
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "呋喃唑酮代谢物",
|
||
xiaolei: "南美白对虾",
|
||
choujian: 3,
|
||
buhegelv: 33.3,
|
||
dengji: "red",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "牛蛙",
|
||
choujian: 116,
|
||
buhegelv: 10.3,
|
||
dengji: "orange",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "鳜鱼",
|
||
choujian: 10,
|
||
buhegelv: 10.0,
|
||
dengji: "orange",
|
||
},
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "鳝鱼",
|
||
choujian: 8,
|
||
buhegelv: 12.5,
|
||
dengji: "orange",
|
||
},
|
||
{
|
||
xiangmu: "氯霉素",
|
||
xiaolei: "蛏",
|
||
choujian: 16,
|
||
buhegelv: 6.3,
|
||
dengji: "yellow",
|
||
},
|
||
{
|
||
xiangmu: "孔雀石绿",
|
||
xiaolei: "黄颡鱼",
|
||
choujian: 31,
|
||
buhegelv: 6.5,
|
||
dengji: "yellow",
|
||
},
|
||
]);
|
||
|
||
const choujianPinfaData = ref([
|
||
// {
|
||
// xiangmu: "噻虫胺",
|
||
// xiaolei: "姜",
|
||
// data: [9.5, 3.077, 10.5, 14.6], // [1月, 2月, 3月, 4月]
|
||
// prediction: 13.2, // 特殊示例值
|
||
// },
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "鳊鱼",
|
||
data: [30.0, 7.143, 28.0, 30.2],
|
||
prediction: 42.6, // 取4月值
|
||
},
|
||
// {
|
||
// xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
// xiaolei: "牛蛙",
|
||
// data: [0.0, 1.471, 2.5, 10.3],
|
||
// prediction: 11.7, // 取4月值
|
||
// },
|
||
// {
|
||
// xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
// xiaolei: "泥鳅",
|
||
// data: [33.3, 0, 7.7, 77.8], // "无"转为 null
|
||
// prediction: 50, // 取4月值
|
||
// },
|
||
// {
|
||
// xiangmu: "呋喃唑酮代谢物",
|
||
// xiaolei: "牛蛙",
|
||
// data: [0.0, 0.0, 1.3, 3.5],
|
||
// prediction: 3.9, // 取4月值
|
||
// },
|
||
// {
|
||
// xiangmu: "呋喃西林代谢物",
|
||
// xiaolei: "牛蛙",
|
||
// data: [0.0, 2.941, 2.5, 3.5],
|
||
// prediction: 3.5, // 取4月值
|
||
// },
|
||
{
|
||
xiangmu: "恩诺沙星(以恩诺沙星与环丙沙星之和计)",
|
||
xiaolei: "黄鱼",
|
||
data: [0.0, 0.0, 2.7, 3.2],
|
||
prediction: 12.5, // 取4月值
|
||
},
|
||
]);
|
||
|
||
const zhifaPinfaData = ref([
|
||
{
|
||
xiangmu: "场所和设备设施清洁维护",
|
||
xiaolei: "场所和设备设施清洁维护",
|
||
data: [50.7, 49.7, 27.3, 22.3],
|
||
prediction: 22.6, // 取4月值
|
||
},
|
||
]);
|
||
|
||
// 新增:品发折线图渲染函数
|
||
const choujianEchartsPinfa = () => {
|
||
// 销毁已有实例,防止重复渲染
|
||
if (main7.value && echarts.getInstanceByDom(main7.value)) {
|
||
echarts.getInstanceByDom(main7.value).dispose();
|
||
}
|
||
var myChart = echarts.init(main7.value);
|
||
const months = ["1月", "2月", "3月", "4月", "5月"];
|
||
const colorList = [
|
||
"#5470C6",
|
||
"#91CC75",
|
||
"#FAC858",
|
||
"#EE6666",
|
||
"#73C0DE",
|
||
"#3BA272",
|
||
"#FC8452",
|
||
];
|
||
// 生成两条series:实线+虚线
|
||
const series = choujianPinfaData.value
|
||
.map((item, idx) => [
|
||
// 实线部分
|
||
{
|
||
name: item.xiaolei,
|
||
type: "line",
|
||
data: [...item.data, null], // 1-4月有值,第5月null
|
||
symbol: "circle",
|
||
symbolSize: 8,
|
||
lineStyle: { type: "solid", width: 2 },
|
||
itemStyle: { color: colorList[idx % colorList.length] },
|
||
connectNulls: true,
|
||
showSymbol: true,
|
||
emphasis: { focus: "series" },
|
||
z: 2,
|
||
},
|
||
// 虚线部分
|
||
{
|
||
name: item.xiaolei + "预测",
|
||
type: "line",
|
||
data: [null, null, null, item.data[3], item.prediction], // 只连4-5月
|
||
symbol: "emptyCircle",
|
||
symbolSize: 10,
|
||
lineStyle: { type: "dashed", width: 2 },
|
||
itemStyle: { color: colorList[idx % colorList.length] },
|
||
connectNulls: true,
|
||
showSymbol: true,
|
||
emphasis: { focus: "series" },
|
||
z: 1,
|
||
tooltip: { show: false }, // 关键:隐藏虚线的tooltip
|
||
},
|
||
])
|
||
.flat();
|
||
// legend只显示品种名
|
||
const legendData = choujianPinfaData.value.map((item) => item.xiaolei);
|
||
const option = {
|
||
title: {
|
||
text: "频发预警",
|
||
left: "center",
|
||
textStyle: { color: "#00ffff", fontSize: 20, fontWeight: "bold" },
|
||
top: 5,
|
||
},
|
||
tooltip: {
|
||
trigger: "axis",
|
||
// valueFormatter: (v) => (v == null ? "无" : v + "%"),
|
||
valueFormatter: (v) => (v == null ? choujianPinfaData.value[0].prediction + "%" : v + "%"),
|
||
},
|
||
legend: {
|
||
data: legendData,
|
||
top: 30,
|
||
textStyle: { color: "#fff" },
|
||
// 只显示主线legend
|
||
selected: legendData.reduce((acc, cur) => {
|
||
acc[cur] = true;
|
||
return acc;
|
||
}, {}),
|
||
},
|
||
grid: { left: 45, right: 30, top: 63, bottom: 45 },
|
||
xAxis: {
|
||
type: "category",
|
||
data: months,
|
||
axisLabel: { color: "#fff" },
|
||
},
|
||
yAxis: {
|
||
show: true,
|
||
type: "value",
|
||
name: "",
|
||
axisLabel: { show: true }, // 隐藏y轴的具体数值
|
||
splitLine: { show: true, lineStyle: { color: "#fff", type: "dashed" } }, // 只显示横线
|
||
},
|
||
series: series,
|
||
};
|
||
myChart.setOption(option);
|
||
};
|
||
|
||
const zhifaEchartsPinfa = () => {
|
||
// 销毁已有实例,防止重复渲染
|
||
if (main8.value && echarts.getInstanceByDom(main8.value)) {
|
||
echarts.getInstanceByDom(main8.value).dispose();
|
||
}
|
||
var myChart = echarts.init(main8.value);
|
||
const months = ["1月", "2月", "3月", "4月", "5月"];
|
||
const colorList = [
|
||
"#5470C6",
|
||
"#91CC75",
|
||
"#FAC858",
|
||
"#EE6666",
|
||
"#73C0DE",
|
||
"#3BA272",
|
||
"#FC8452",
|
||
];
|
||
// 生成两条series:实线+虚线
|
||
const series = zhifaPinfaData.value
|
||
.map((item, idx) => [
|
||
// 实线部分
|
||
{
|
||
name: item.xiaolei,
|
||
type: "line",
|
||
data: [...item.data, null], // 1-4月有值,第5月null
|
||
symbol: "circle",
|
||
symbolSize: 8,
|
||
lineStyle: { type: "solid", width: 2 },
|
||
itemStyle: { color: colorList[idx % colorList.length] },
|
||
connectNulls: true,
|
||
showSymbol: true,
|
||
emphasis: { focus: "series" },
|
||
z: 2,
|
||
},
|
||
// 虚线部分
|
||
{
|
||
name: item.xiaolei + "预测",
|
||
type: "line",
|
||
data: [null, null, null, item.data[3], item.prediction], // 只连4-5月
|
||
symbol: "emptyCircle",
|
||
symbolSize: 10,
|
||
lineStyle: { type: "dashed", width: 2 },
|
||
itemStyle: { color: colorList[idx % colorList.length] },
|
||
connectNulls: true,
|
||
showSymbol: true,
|
||
emphasis: { focus: "series" },
|
||
z: 1,
|
||
tooltip: { show: false }, // 关键:隐藏虚线的tooltip
|
||
},
|
||
])
|
||
.flat();
|
||
// legend只显示品种名
|
||
const legendData = zhifaPinfaData.value.map((item) => item.xiaolei);
|
||
const option = {
|
||
title: {
|
||
text: "频发预警",
|
||
left: "center",
|
||
textStyle: { color: "#00ffff", fontSize: 20, fontWeight: "bold" },
|
||
top: 5,
|
||
},
|
||
tooltip: {
|
||
trigger: "axis",
|
||
valueFormatter: (v) => (v == null ? zhifaPinfaData.value[0].prediction + "%" : v + "%"),
|
||
// formatter: '{b0}: {c0}<br />{b1}: {c1}'
|
||
|
||
},
|
||
legend: {
|
||
data: legendData,
|
||
top: 30,
|
||
textStyle: { color: "#fff" },
|
||
// 只显示主线legend
|
||
selected: legendData.reduce((acc, cur) => {
|
||
acc[cur] = true;
|
||
return acc;
|
||
}, {}),
|
||
},
|
||
grid: { left: 45, right: 30, top: 63, bottom: 45 },
|
||
xAxis: {
|
||
type: "category",
|
||
data: months,
|
||
axisLabel: { color: "#fff" },
|
||
},
|
||
yAxis: {
|
||
show: true,
|
||
type: "value",
|
||
name: "",
|
||
axisLabel: { show: true }, // 隐藏y轴的具体数值
|
||
splitLine: { show: true, lineStyle: { color: "#fff", type: "dashed" } }, // 只显示横线
|
||
},
|
||
series: series,
|
||
};
|
||
myChart.setOption(option);
|
||
};
|
||
|
||
const jubaoGaofaData = ref([
|
||
{
|
||
huanjie: "销售环节",
|
||
zhonglei: "虚假宣传",
|
||
tousulv: "7.05%",
|
||
dengji: "red",
|
||
},
|
||
{
|
||
huanjie: "销售环节",
|
||
zhonglei: "腐败变质",
|
||
tousulv: "3.21%",
|
||
dengji: "red",
|
||
}, {
|
||
huanjie: "销售环节",
|
||
zhonglei: "存在异物",
|
||
tousulv: "3.18%",
|
||
dengji: "red",
|
||
}, {
|
||
huanjie: "销售环节",
|
||
zhonglei: "原料处理不当",
|
||
tousulv: "2.04%",
|
||
dengji: "yellow",
|
||
}, {
|
||
huanjie: "销售环节",
|
||
zhonglei: "虚假宣传",
|
||
tousulv: "1.97%",
|
||
dengji: "yellow",
|
||
},
|
||
]);
|
||
|
||
const jubaoPinfaData = ref([
|
||
{
|
||
zhuti: "上海盒马网络科技有限公司",
|
||
leibie: "水果类",
|
||
hegelv: "100.0%(65/65)",
|
||
zhonglei: "腐败变质",
|
||
wentishu: 3,
|
||
dengji: "yellow",
|
||
},
|
||
{
|
||
zhuti: "上海盒马网络科技有限公司",
|
||
leibie: "畜禽肉及副产品",
|
||
hegelv: "100.0%(123/123)",
|
||
zhonglei: "腐败变质",
|
||
wentishu: 3,
|
||
dengji: "yellow",
|
||
},
|
||
{
|
||
zhuti: "上海盒马网络科技有限公司",
|
||
leibie: "水产品",
|
||
hegelv: "99.2%(251/253)",
|
||
zhonglei: "腐败变质",
|
||
wentishu: 3,
|
||
dengji: "yellow",
|
||
},
|
||
]);
|
||
|
||
const highlightGraphNodeByName = (nodeName: string) => {
|
||
// 先取消所有高亮
|
||
chartRelationship.dispatchAction({
|
||
type: "downplay",
|
||
seriesIndex: 0,
|
||
});
|
||
// 高亮目标节点
|
||
chartRelationship.dispatchAction({
|
||
type: "highlight",
|
||
seriesIndex: 0,
|
||
name: nodeName,
|
||
});
|
||
};
|
||
|
||
const handleRowClick = (item: any, index: number) => {
|
||
console.log(item, index);
|
||
|
||
// 将当前行数据移到首行
|
||
if (index !== 0) {
|
||
jubaoGaofaData.value.splice(index, 1); // 删除当前行
|
||
jubaoGaofaData.value.unshift(item); // 插入到首行
|
||
}
|
||
};
|
||
|
||
|
||
const fancyBtn = ref(null)
|
||
const ripple = ref(null)
|
||
const handleFancyClick = (e: MouseEvent) => {
|
||
const btn = fancyBtn.value as HTMLElement
|
||
const span = ripple.value as HTMLElement
|
||
if (!btn || !span) return
|
||
const rect = btn.getBoundingClientRect()
|
||
const size = Math.max(rect.width, rect.height)
|
||
span.style.width = span.style.height = size + 'px'
|
||
span.style.left = (e.clientX - rect.left - size / 2) + 'px'
|
||
span.style.top = (e.clientY - rect.top - size / 2) + 'px'
|
||
span.classList.add('show')
|
||
setTimeout(() => span.classList.remove('show'), 500)
|
||
|
||
//接下来展示或隐藏关联关系图
|
||
if (relationShow.value) {
|
||
// 隐藏动画:先播放收回动画,动画完成后再隐藏
|
||
isAnimating.value = true
|
||
relationShow.value = false
|
||
setTimeout(() => {
|
||
isAnimating.value = false
|
||
}, 300) // 动画持续时间
|
||
} else {
|
||
// 显示动画:先显示元素(但不可见),然后播放弹出动画
|
||
relationShow.value = true
|
||
// 延迟一帧再开始动画,确保元素已经渲染
|
||
requestAnimationFrame(() => {
|
||
isAnimating.value = true
|
||
setTimeout(() => {
|
||
isAnimating.value = false
|
||
}, 300) // 动画持续时间
|
||
})
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.card1 {
|
||
position: absolute;
|
||
top: 10px;
|
||
right: 10px;
|
||
width: 30px;
|
||
height: 30px;
|
||
background: transparent;
|
||
border: none;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.card-icon1 {
|
||
font-size: 16px;
|
||
color: white;
|
||
}
|
||
|
||
.example-showcase .el-dropdown-link {
|
||
cursor: pointer;
|
||
/* color: var(--el-color-primary); */
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
#tooltip {
|
||
transition: all 0.3s ease-out;
|
||
}
|
||
|
||
.shanghaimap {
|
||
position: absolute;
|
||
/* 绝对定位 */
|
||
top: 18%;
|
||
/* 从容器的顶部开始 */
|
||
left: 26.5%;
|
||
/* 从容器的左侧开始 */
|
||
width: 47%;
|
||
/* 宽度占满整个容器 */
|
||
height: 75%;
|
||
/* 高度占满整个容器 */
|
||
z-index: 5;
|
||
/* 确保大盒子在小盒子后面 */
|
||
display: flex;
|
||
/* 使用 Flexbox 布局 */
|
||
justify-content: center;
|
||
/* 水平居中对齐 */
|
||
align-items: center;
|
||
/* 垂直居中对齐 */
|
||
}
|
||
|
||
.bar-show {
|
||
max-width: 100px;
|
||
/* 设置最大宽度 */
|
||
white-space: nowrap;
|
||
/* 禁止换行 */
|
||
overflow: hidden;
|
||
/* 超出部分隐藏 */
|
||
text-overflow: ellipsis;
|
||
/* 使用省略号表示超出部分 */
|
||
}
|
||
|
||
@keyframes fadeInOut {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(-10px);
|
||
}
|
||
|
||
50% {
|
||
opacity: 1;
|
||
}
|
||
|
||
100% {
|
||
opacity: 0;
|
||
transform: translateY(10px);
|
||
}
|
||
}
|
||
|
||
.scroll-wrapper {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.scroll-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 8px 16px;
|
||
color: #00ffff;
|
||
font-weight: bold;
|
||
border-bottom: 2px solid rgba(0, 255, 255, 0.3);
|
||
background: rgba(0, 0, 0, 0.2);
|
||
font-size: 10px;
|
||
|
||
.scroll-header-text {
|
||
flex: 1;
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.scroll-container {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
background: rgba(0, 0, 0, 0.2);
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.scroll-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 8px 16px;
|
||
color: rgb(204, 203, 203);
|
||
font-size: 8px;
|
||
}
|
||
|
||
.scroll-item-text {
|
||
flex: 1;
|
||
text-align: center;
|
||
}
|
||
|
||
.scroll-header-title {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 20px;
|
||
color: #00ffff;
|
||
font-weight: bold;
|
||
/* border-bottom: 2px solid rgba(0, 255, 255, 0.3); */
|
||
background: rgba(0, 0, 0, 0.2);
|
||
padding-top: 3px;
|
||
}
|
||
|
||
.ripple {
|
||
position: absolute;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.4);
|
||
transform: scale(0);
|
||
pointer-events: none;
|
||
transition: transform 0.5s, opacity 0.5s;
|
||
opacity: 0;
|
||
z-index: 1;
|
||
}
|
||
|
||
.ripple.show {
|
||
transform: scale(2.5);
|
||
opacity: 1;
|
||
transition: transform 0.5s, opacity 0.5s;
|
||
}
|
||
|
||
/* 弹出动画 */
|
||
@keyframes popup {
|
||
0% {
|
||
opacity: 0;
|
||
transform: scale(0) translate(0, 0);
|
||
}
|
||
50% {
|
||
opacity: 0.8;
|
||
transform: scale(0.8) translate(0, -20px);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: scale(1) translate(0, 0);
|
||
}
|
||
}
|
||
|
||
/* 收回动画 */
|
||
@keyframes shrink {
|
||
0% {
|
||
opacity: 1;
|
||
transform: scale(1) translate(0, 0);
|
||
}
|
||
50% {
|
||
opacity: 0.8;
|
||
transform: scale(0.8) translate(0, -20px);
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
transform: scale(0) translate(0, 0);
|
||
}
|
||
}
|
||
|
||
.animate-popup {
|
||
animation: popup 0.3s ease-out forwards;
|
||
transform-origin: bottom right;
|
||
}
|
||
|
||
.animate-shrink {
|
||
animation: shrink 0.3s ease-in forwards;
|
||
transform-origin: bottom right;
|
||
}
|
||
|
||
/* 初始状态 - 隐藏且缩放为0 */
|
||
.opacity-0.scale-0 {
|
||
opacity: 0 !important;
|
||
transform: scale(0) !important;
|
||
transition: none !important;
|
||
}
|
||
</style>
|