123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- <template>
- <div class="left_bottom">
- <div class="left_bottom-title flex">
- <div class="flex items-center">
- <img src="@/assets/img/home/title_arrow.png" alt="" />
- 预警热点
- </div>
- <el-dropdown @command="handleCommand">
- <el-button link class="link-button">
- {{ areaText }}
- <el-icon class="el-icon--right">
- <arrow-down />
- </el-icon>
- </el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item
- v-for="item in areaList"
- :key="item.id"
- :command="item"
- >{{ item.areaName }}</el-dropdown-item
- >
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </div>
- <div class="left_bottom-content">
- <template v-if="list.length">
- <v-chart
- class="chart"
- :option="option"
- :loading="loading"
- :loading-options="loadingOptions"
- />
- </template>
- <template v-else>
- <EmptyCom></EmptyCom>
- </template>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { onMounted, ref, watch } from "vue";
- import { ArrowDown } from "@element-plus/icons-vue";
- import { getArea, hotSpot } from "@/api/home";
- import dayjs from "dayjs";
- import EmptyCom from "@/components/empty-com";
- import {
- getCurrentCityCode,
- getCurrentCityName,
- loadingOptions,
- } from "@/utils/constants";
- import { graphic } from "echarts/core";
- import { arraySortByKey } from "@/utils/tools";
- const props = defineProps({
- dateArray: {
- type: Array,
- default: () => [],
- },
- });
- const date = ref([]);
- const loading = ref(false);
- const option = ref<any>({});
- watch(
- () => props.dateArray,
- (val: any) => {
- date.value = val;
- },
- { immediate: true }
- );
- watch(
- () => props.dateArray,
- () => {
- getData();
- }
- );
- const areaCode = ref(getCurrentCityCode());
- const areaText = ref(getCurrentCityName());
- const list = ref<any>([]);
- const getData = async () => {
- loading.value = true;
- try {
- const { result } = await hotSpot({
- StartTime: dayjs(date.value[0]).format("YYYY-MM-DD"),
- EndTime: dayjs(date.value[1]).format("YYYY-MM-DD"),
- AreaCode: areaCode.value,
- });
- list.value = result;
- /*
- list.value.push({
- hotspotId: "1925",
- hotspotName: "不按规定的内容和方式明码标价",
- sumCount: 20,
- hotspotSpliceName: "市场管理-物价-价格违法违规行为-不执行法定的价格干预措施、紧急措施-不按规定的内容和方式明码标价"
- })
- */
- const category = arraySortByKey(result, "sumCount");
- const charts = {
- // 按顺序排列从大到小
- cityList: category.map((item: any) => item.hotspotName),
- cityData: category.map((item: any) => item.sumCount),
- };
- const top10CityList = charts.cityList;
- const top10CityData = charts.cityData;
- const color = ["#ff9500", "#02d8f9", "#027fff"];
- const color1 = ["#ffb349", "#70e9fc", "#4aa4ff"];
- let lineY = [];
- let lineT = [];
- for (let i = 0; i < charts.cityList.length; i++) {
- let x = i;
- if (x > 1) {
- x = 2;
- }
- const data = {
- name: charts.cityList[i],
- color: color[x],
- value: top10CityData[i],
- barGap: "-100%",
- itemStyle: {
- show: true,
- color: new graphic.LinearGradient(
- 0,
- 0,
- 1,
- 0,
- [
- {
- offset: 0,
- color: color[x],
- },
- {
- offset: 1,
- color: color1[x],
- },
- ],
- false
- ),
- borderRadius: 10,
- },
- emphasis: {
- itemStyle: {
- shadowBlur: 15,
- shadowColor: "rgba(0, 0, 0, 0.1)",
- },
- },
- };
- const data1 = {
- value: top10CityData[0],
- itemStyle: {
- color: "#001235",
- borderRadius: 10,
- },
- };
- lineY.push(data);
- lineT.push(data1);
- }
- option.value = {
- backgroundColor: "rgba(0, 0, 0, 0)",
- title: {
- show: false,
- },
- tooltip: {
- trigger: "axis",
- axisPointer: {
- type: "shadow",
- },
- formatter: function (params: any) {
- let tar;
- if (params[0].seriesIndex === 0) {
- tar = params[0];
- } else {
- tar = params[1];
- }
- return tar.marker + tar.name + "<br/>" + " 当前数量: " + tar.value;
- },
- enterable: true, //滚动条
- confine: true,
- extraCssText: "max-width:90%;max-height:83%;overflow:auto;",
- //改变提示框的位置 不超出屏幕显示
- position: function (point, params, dom, rect, size) {
- //其中point为当前鼠标的位置,
- //size中有两个属性:viewSize和contentSize,分别为外层div和tooltip提示框的大小
- // 鼠标坐标和提示框位置的参考坐标系是:以外层div的左上角那一点为原点,x轴向右,y轴向下
- // 提示框位置
- let x = 0; // x坐标位置
- let y = 0; // y坐标位置
- // 当前鼠标位置
- const pointX = point[0];
- const pointY = point[1];
- // 提示框大小
- const boxWidth = size.contentSize[0];
- const boxHeight = size.contentSize[1];
- // boxWidth > pointX 说明鼠标左边放不下提示框
- if (boxWidth > pointX) {
- x = 5;
- } else {
- // 左边放的下
- x = pointX - boxWidth;
- }
- // boxHeight > pointY 说明鼠标上边放不下提示框
- if (boxHeight > pointY) {
- y = 5;
- } else {
- // 上边放得下
- y = pointY - boxHeight;
- }
- return [x, y];
- },
- },
- grid: {
- borderWidth: 0,
- top: "5%",
- left: "5%",
- right: "15%",
- bottom: "10%",
- },
- color: color,
- yAxis: [
- {
- type: "category",
- inverse: true,
- axisTick: {
- show: false,
- },
- axisLine: {
- show: false,
- },
- axisLabel: {
- show: false,
- inside: false,
- },
- data: top10CityList,
- },
- {
- type: "category",
- inverse: true,
- axisLine: {
- show: false,
- },
- axisTick: {
- show: false,
- },
- axisLabel: {
- show: true,
- inside: false,
- verticalAlign: "middle",
- lineHeight: "40",
- color: "#fff",
- fontSize: "14",
- fontFamily: "PingFangSC-Regular",
- formatter: function (val) {
- return `${val}`;
- },
- },
- splitArea: {
- show: false,
- },
- splitLine: {
- show: false,
- },
- data: top10CityData,
- },
- ],
- xAxis: {
- type: "value",
- axisTick: {
- show: false,
- },
- axisLine: {
- show: false,
- },
- splitLine: {
- show: false,
- },
- axisLabel: {
- show: false,
- },
- },
- series: [
- {
- type: "bar",
- zLevel: 2,
- barWidth: "10px",
- data: lineY,
- label: {
- color: "#b3ccf8",
- show: true,
- position: [0, "-18px"],
- fontSize: 16,
- width: 40,
- formatter: function (a) {
- let num = "";
- let str = "";
- if (a.dataIndex + 1 < 10) {
- num = "0" + (a.dataIndex + 1);
- } else {
- num = a.dataIndex + 1;
- }
- let names = "";
- if (a.name.length > 25) {
- names = a.name.slice(0, 25) + "...";
- } else {
- names = a.name;
- }
- if (a.dataIndex === 0) {
- str = `{color1|${num}} {color4|${names}}`;
- } else if (a.dataIndex === 1) {
- str = `{color2|${num}} {color4|${names}}`;
- } else {
- str = `{color3|${num}} {color4|${names}}`;
- }
- return str;
- },
- rich: {
- color1: {
- color: "#ff9500",
- },
- color2: {
- color: "#02d8f9",
- },
- color3: {
- color: "#027fff",
- },
- color4: {
- color: "#e5eaff",
- },
- },
- },
- },
- ],
- };
- loading.value = false;
- } catch (e) {
- console.log(e);
- loading.value = false;
- }
- };
- // 选择省市区
- const handleCommand = (command: any) => {
- areaCode.value = command.id;
- areaText.value = command.areaName;
- getData();
- };
- const areaList = ref([]);
- const getAreaData = async () => {
- try {
- const res = await getArea();
- areaList.value = res.result ?? [];
- } catch (e) {
- console.log(e);
- }
- };
- onMounted(() => {
- getData();
- getAreaData();
- });
- </script>
- <style scoped lang="scss">
- .left_bottom {
- padding: 0 30px;
- &-title {
- font-size: 20px;
- color: #fff;
- justify-content: space-between;
- align-items: center;
- }
- &-content {
- height: calc(100% - 30px);
- }
- }
- :deep(.link-button) {
- cursor: pointer;
- color: #7dbdec;
- display: flex;
- align-items: center;
- }
- </style>
|