|
@@ -3,35 +3,26 @@
|
|
|
<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">
|
|
|
+ <div class="left_bottom-content" v-loading="loading">
|
|
|
<template v-if="list.length">
|
|
|
- <v-chart
|
|
|
- class="chart"
|
|
|
- :option="option"
|
|
|
- :loading="loading"
|
|
|
- :loading-options="loadingOptions"
|
|
|
- />
|
|
|
+ <div class="scroll">
|
|
|
+ <div class="scroll-item" v-for="(item, index) in list" :key="index">
|
|
|
+ <span class="scroll-item-area" :class="index <= 2 ? 'three' : ''"
|
|
|
+ >NO.{{ index + 1 }}</span
|
|
|
+ >
|
|
|
+ <TextTooltip
|
|
|
+ :content="item.visitOrgName"
|
|
|
+ className="scroll-item-title-ju"
|
|
|
+ ></TextTooltip>
|
|
|
+ <span class="scroll-item-hotspot-ju"
|
|
|
+ ><CountUp :endVal="item.visitCount" :duration="2" />(件)</span
|
|
|
+ >
|
|
|
+ <span class="scroll-item-num">{{ item.satisfiedRate }}%</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
<empty v-else />
|
|
|
</div>
|
|
@@ -39,19 +30,20 @@
|
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
|
import { defineAsyncComponent, onMounted, ref, watch } from "vue";
|
|
|
-import { ArrowDown } from "@element-plus/icons-vue";
|
|
|
-import { getArea } from "@/api/home";
|
|
|
import dayjs from "dayjs";
|
|
|
-import { loadingOptions } from "@/utils/constants";
|
|
|
-import { graphic } from "echarts/core";
|
|
|
-import { arraySortByKey } from "@/utils/tools";
|
|
|
-import { leftBottomData } from "api/judicial";
|
|
|
-import { useThemeConfig } from "@/stores/themeConfig";
|
|
|
-import { storeToRefs } from "pinia";
|
|
|
+import { orgSatis } from "api/judicial";
|
|
|
+import mittBus from "@/utils/mitt";
|
|
|
|
|
|
+const TextTooltip = defineAsyncComponent(
|
|
|
+ () => import("@/components/TextTooltip/index.vue")
|
|
|
+);
|
|
|
const Empty = defineAsyncComponent(
|
|
|
() => import("@/components/Empty/index.vue")
|
|
|
);
|
|
|
+const CountUp = defineAsyncComponent(
|
|
|
+ () => import("@/components/Count-up/index.vue")
|
|
|
+);
|
|
|
+
|
|
|
const props = defineProps({
|
|
|
dateArray: {
|
|
|
type: Array,
|
|
@@ -60,7 +52,6 @@ const props = defineProps({
|
|
|
});
|
|
|
const date = ref([]);
|
|
|
const loading = ref(false);
|
|
|
-const option = ref<any>({});
|
|
|
watch(
|
|
|
() => props.dateArray,
|
|
|
(val: any) => {
|
|
@@ -71,304 +62,143 @@ watch(
|
|
|
|
|
|
watch(
|
|
|
() => props.dateArray,
|
|
|
- () => {
|
|
|
+ (val: any) => {
|
|
|
getData();
|
|
|
}
|
|
|
);
|
|
|
-const storesThemeConfig = useThemeConfig();
|
|
|
-const { themeConfig } = storeToRefs(storesThemeConfig);
|
|
|
-const areaCode = ref(themeConfig.value.cityCode);
|
|
|
-const areaText = ref(themeConfig.value.cityName);
|
|
|
const list = ref<any>([]);
|
|
|
+const AreaCode = ref(null);
|
|
|
const getData = async () => {
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
- const { result } = await leftBottomData({
|
|
|
+ const { result } = await orgSatis({
|
|
|
StartTime: dayjs(date.value[0]).format("YYYY-MM-DD"),
|
|
|
EndTime: dayjs(date.value[1]).format("YYYY-MM-DD"),
|
|
|
- AreaCode: areaCode.value,
|
|
|
+ AreaCode: AreaCode.value,
|
|
|
});
|
|
|
- list.value = result;
|
|
|
- const category = arraySortByKey(list.value, "sumCount");
|
|
|
- const charts = {
|
|
|
- // 按顺序排列从大到小
|
|
|
- cityList: category.map((item: any) => item.eventTypeName),
|
|
|
- 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,
|
|
|
- formatter: function (a) {
|
|
|
- let num = "";
|
|
|
- let str = "";
|
|
|
- if (a.dataIndex + 1 < 10) {
|
|
|
- num = "0" + (a.dataIndex + 1);
|
|
|
- } else {
|
|
|
- num = a.dataIndex + 1;
|
|
|
- }
|
|
|
- if (a.dataIndex === 0) {
|
|
|
- str = `{color1|${num}} {color4|${a.name}}`;
|
|
|
- } else if (a.dataIndex === 1) {
|
|
|
- str = `{color2|${num}} {color4|${a.name}}`;
|
|
|
- } else {
|
|
|
- str = `{color3|${num}} {color4|${a.name}}`;
|
|
|
- }
|
|
|
- return str;
|
|
|
- },
|
|
|
- rich: {
|
|
|
- color1: {
|
|
|
- color: "#ff9500",
|
|
|
- fontWeight: 700,
|
|
|
- },
|
|
|
- color2: {
|
|
|
- color: "#02d8f9",
|
|
|
- fontWeight: 700,
|
|
|
- },
|
|
|
- color3: {
|
|
|
- color: "#027fff",
|
|
|
- fontWeight: 700,
|
|
|
- },
|
|
|
- color4: {
|
|
|
- color: "#e5eaff",
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
- ],
|
|
|
- };
|
|
|
+ // list.value = [...result, ...result, ...result, ...result];
|
|
|
+ list.value = [...result];
|
|
|
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();
|
|
|
+ mittBus.on("SelectArea", (data: any) => {
|
|
|
+ AreaCode.value = data.areaCode;
|
|
|
+ getData();
|
|
|
+ });
|
|
|
});
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
.left_bottom {
|
|
|
padding: 0 30px;
|
|
|
+ font-size: 15px;
|
|
|
|
|
|
&-title {
|
|
|
- font-size: 20px;
|
|
|
color: #fff;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
&-content {
|
|
|
- height: calc(100% - 30px);
|
|
|
+ margin-top: 15px;
|
|
|
+ height: 100%;
|
|
|
+
|
|
|
+ .scroll {
|
|
|
+ height: 500px;
|
|
|
+ overflow: auto;
|
|
|
+
|
|
|
+ &-item {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px 5px;
|
|
|
+ color: #d2d4d5;
|
|
|
+ margin-bottom: 15px;
|
|
|
+
|
|
|
+ &:nth-child(odd) {
|
|
|
+ background-color: rgba(255, 255, 255, 0.1);
|
|
|
+ border-radius: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-area {
|
|
|
+ display: inline-block;
|
|
|
+ background-color: #69bbf6;
|
|
|
+ padding: 0 6px;
|
|
|
+ color: #333;
|
|
|
+ border-top-left-radius: 4px;
|
|
|
+ border-bottom-left-radius: 4px;
|
|
|
+ white-space: nowrap;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &:after {
|
|
|
+ content: "";
|
|
|
+ border-left: 8px solid #69bbf6;
|
|
|
+ border-right: 12px solid transparent;
|
|
|
+ border-top: 12px solid transparent;
|
|
|
+ border-bottom: 10px solid transparent;
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ position: absolute;
|
|
|
+ right: -19px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .three {
|
|
|
+ background-color: #eca455;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .three:after {
|
|
|
+ content: "";
|
|
|
+ border-left: 8px solid #eca455;
|
|
|
+ border-right: 12px solid transparent;
|
|
|
+ border-top: 12px solid transparent;
|
|
|
+ border-bottom: 10px solid transparent;
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ position: absolute;
|
|
|
+ right: -19px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-title {
|
|
|
+ width: 50%;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ margin-left: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-hotspot {
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ flex: 1;
|
|
|
+ margin-left: 30px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-:deep(.link-button) {
|
|
|
- cursor: pointer;
|
|
|
- color: #7dbdec;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
+.count-up-wrap {
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+.scroll-item-title-ju {
|
|
|
+ width: 50%;
|
|
|
+ margin-left: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.scroll-item-hotspot-ju {
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ flex: 1;
|
|
|
+ margin-left: 30px;
|
|
|
}
|
|
|
</style>
|