|
@@ -1,31 +1,59 @@
|
|
|
<template>
|
|
|
<div class="left-center">
|
|
|
- <div class="left-center-title flex items-center">
|
|
|
- <img src="@/assets/img/home/title_arrow.png" alt="" />
|
|
|
- 受理类型办件分析
|
|
|
+ <div class="left-center-title flex items-center justify-between">
|
|
|
+ 分析时间:
|
|
|
+ <el-date-picker
|
|
|
+ v-model="timeValue"
|
|
|
+ type="daterange"
|
|
|
+ unlink-panels
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始时间"
|
|
|
+ end-placeholder="结束时间"
|
|
|
+ :shortcuts="shortcuts"
|
|
|
+ :clearable="false"
|
|
|
+ @change="changeDate"
|
|
|
+ />
|
|
|
</div>
|
|
|
- <div class="left-center-content">
|
|
|
- <template v-if="xData.length">
|
|
|
+ <div class="left-center-content flex justify-center">
|
|
|
+ <div class="w-full">
|
|
|
<v-chart
|
|
|
class="chart"
|
|
|
:option="option"
|
|
|
:loading="loading"
|
|
|
:loading-options="loadingOptions"
|
|
|
+ style="height: calc(100% - 50px)"
|
|
|
/>
|
|
|
- </template>
|
|
|
- <empty v-else />
|
|
|
+ <p class="w-full" style="text-align: center">已办件数</p>
|
|
|
+ </div>
|
|
|
+ <div class="w-full">
|
|
|
+ <v-chart
|
|
|
+ class="chart1"
|
|
|
+ :option="option1"
|
|
|
+ :loading="loading"
|
|
|
+ :loading-options="loadingOptions"
|
|
|
+ style="height: calc(100% - 50px)"
|
|
|
+ />
|
|
|
+ <p class="w-full" style="text-align: center">在办件数</p>
|
|
|
+ </div>
|
|
|
+ <div class="w-full">
|
|
|
+ <v-chart
|
|
|
+ class="chart2"
|
|
|
+ :option="option2"
|
|
|
+ :loading="loading"
|
|
|
+ :loading-options="loadingOptions"
|
|
|
+ style="height: calc(100% - 50px)"
|
|
|
+ />
|
|
|
+ <p class="w-full" style="text-align: center">上报数</p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted, watch, defineAsyncComponent } from "vue";
|
|
|
+import { ref, onMounted, watch } from "vue";
|
|
|
import { acceptType } from "@/api/home";
|
|
|
import dayjs from "dayjs";
|
|
|
-import { loadingOptions } from "@/utils/constants";
|
|
|
+import { loadingOptions, shortcuts } from "@/utils/constants";
|
|
|
|
|
|
-const Empty = defineAsyncComponent(
|
|
|
- () => import("@/components/Empty/index.vue")
|
|
|
-);
|
|
|
const props = defineProps({
|
|
|
dateArray: {
|
|
|
type: Array,
|
|
@@ -42,6 +70,16 @@ watch(
|
|
|
{ immediate: true }
|
|
|
);
|
|
|
|
|
|
+const emit = defineEmits(["changeDate"]);
|
|
|
+const timeValue = ref<any>([
|
|
|
+ dayjs().subtract(1, "month").toDate(),
|
|
|
+ dayjs().toDate(),
|
|
|
+]); //默认近一个月
|
|
|
+emit("changeDate", timeValue.value);
|
|
|
+const changeDate = (val: any) => {
|
|
|
+ emit("changeDate", val);
|
|
|
+};
|
|
|
+
|
|
|
watch(
|
|
|
() => props.dateArray,
|
|
|
(val: any) => {
|
|
@@ -50,7 +88,8 @@ watch(
|
|
|
);
|
|
|
|
|
|
const option = ref({});
|
|
|
-const xData = ref([]);
|
|
|
+const option1 = ref({});
|
|
|
+const option2 = ref({});
|
|
|
const loading = ref(true);
|
|
|
const getData = async () => {
|
|
|
loading.value = true;
|
|
@@ -59,171 +98,219 @@ const getData = async () => {
|
|
|
StartTime: dayjs(date.value[0]).format("YYYY-MM-DD"),
|
|
|
EndTime: dayjs(date.value[1]).format("YYYY-MM-DD"),
|
|
|
});
|
|
|
- xData.value = result.map((item: any) => item.acceptType);
|
|
|
- const totalData = result.reduce((pre: any, cur: any) => {
|
|
|
- pre.push(cur.sumCount);
|
|
|
- return pre;
|
|
|
- }, []);
|
|
|
- const handlingCount = result.reduce((pre: any, cur: any) => {
|
|
|
- pre.push(cur.handlingCount);
|
|
|
- return pre;
|
|
|
- }, []);
|
|
|
- const filedCount = result.reduce((pre: any, cur: any) => {
|
|
|
- pre.push(cur.filedCount);
|
|
|
- return pre;
|
|
|
- }, []);
|
|
|
- const overTimeCount = result.reduce((pre: any, cur: any) => {
|
|
|
- pre.push(cur.overTimeCount);
|
|
|
- return pre;
|
|
|
- }, []);
|
|
|
- // mock 数据
|
|
|
- let dataArr = {
|
|
|
- xData: xData.value,
|
|
|
- result: [
|
|
|
- { name: "总数", data: totalData },
|
|
|
- { name: "已办", data: handlingCount },
|
|
|
- { name: "在办", data: filedCount },
|
|
|
- { name: "超期", data: overTimeCount },
|
|
|
- ],
|
|
|
- series: [],
|
|
|
- };
|
|
|
- const diamondData = dataArr.result.reduce((pre, cur, index) => {
|
|
|
- pre[index] = cur.data.map(
|
|
|
- (el, id) => el + (pre[index - 1] ? pre[index - 1][id] : 0)
|
|
|
- );
|
|
|
- return pre;
|
|
|
- }, []);
|
|
|
- const color = [
|
|
|
- [
|
|
|
- { offset: 0, color: "#efff37" },
|
|
|
- { offset: 1, color: "#d5e700" },
|
|
|
- ],
|
|
|
- [
|
|
|
- { offset: 0, color: "#32ffee" },
|
|
|
- { offset: 1, color: "#00e8d5" },
|
|
|
- ],
|
|
|
- [
|
|
|
- { offset: 0, color: "#46c9ff" },
|
|
|
- { offset: 1, color: "#00b4ff" },
|
|
|
- ],
|
|
|
- [
|
|
|
- { offset: 0, color: "#54a0ff" },
|
|
|
- { offset: 1, color: "#1f83ff" },
|
|
|
- ],
|
|
|
- ];
|
|
|
-
|
|
|
- dataArr.series = dataArr.result.reduce((p, c, i, array) => {
|
|
|
- p.push(
|
|
|
+ const data = { name: "已办件数", value: 91.22, data: 2020 };
|
|
|
+ setOption(data);
|
|
|
+ setOption1(data);
|
|
|
+ setOption2(data);
|
|
|
+ loading.value = false;
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+// 圆环--开始色
|
|
|
+let baseColorStart = "#45A5DB";
|
|
|
+// 圆环--结束色
|
|
|
+let baseColorEnd = "#0A6BC5";
|
|
|
+// 圆环--环底色
|
|
|
+let ringColor = "#112A5D";
|
|
|
+const setOption = (data: any) => {
|
|
|
+ option.value = {
|
|
|
+ // 还原内部文字
|
|
|
+ title: [
|
|
|
+ {
|
|
|
+ text: data.value + "%",
|
|
|
+ top: "40%",
|
|
|
+ right: "30%",
|
|
|
+ textStyle: {
|
|
|
+ color: "#fff",
|
|
|
+ fontSize: 18,
|
|
|
+ fontWeight: 400,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: data.data,
|
|
|
+ top: "53%",
|
|
|
+ right: "center",
|
|
|
+ textStyle: {
|
|
|
+ color: "#6F87B1",
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 400,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ series: {
|
|
|
+ name: "已办件数",
|
|
|
+ type: "pie",
|
|
|
+ radius: ["60%", "85%"],
|
|
|
+ silent: true,
|
|
|
+ clockwise: true,
|
|
|
+ startAngle: 90,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ data: [
|
|
|
{
|
|
|
- z: i + 1,
|
|
|
- stack: true,
|
|
|
- type: "bar",
|
|
|
- name: c.name,
|
|
|
- barWidth: 15,
|
|
|
- data: c.data,
|
|
|
+ value: data.value,
|
|
|
itemStyle: {
|
|
|
color: {
|
|
|
type: "linear",
|
|
|
x: 0,
|
|
|
- x2: 0,
|
|
|
y: 0,
|
|
|
+ x2: 0,
|
|
|
y2: 1,
|
|
|
- colorStops: color[i],
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: baseColorStart,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: baseColorEnd,
|
|
|
+ },
|
|
|
+ ],
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
- z: i + 10,
|
|
|
- name: c.name,
|
|
|
- type: "pictorialBar",
|
|
|
- symbolPosition: "end",
|
|
|
- symbol: "circle",
|
|
|
- symbolOffset: [0, "-50%"],
|
|
|
- symbolSize: [15, 12.5],
|
|
|
- data: diamondData[i],
|
|
|
+ name: "待办件数",
|
|
|
+ value: 100 - data.value,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
itemStyle: {
|
|
|
- color: color[i + 1] ? color[i + 1][0].color : null,
|
|
|
+ // 圆环底色
|
|
|
+ color: ringColor,
|
|
|
},
|
|
|
- tooltip: { show: false },
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- return p;
|
|
|
- }, []);
|
|
|
-
|
|
|
- // 最上边顶
|
|
|
- dataArr.series.push({
|
|
|
- name: dataArr.result[dataArr.result.length - 1].name,
|
|
|
- z: 20,
|
|
|
- type: "pictorialBar",
|
|
|
- symbolPosition: "end",
|
|
|
- data: diamondData[diamondData.length - 1],
|
|
|
- symbol: "circle",
|
|
|
- symbolOffset: ["0%", "-50%"],
|
|
|
- symbolSize: [15, 12.5],
|
|
|
- itemStyle: {
|
|
|
- color: color[color.length - 1][0].color,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ };
|
|
|
+};
|
|
|
+const setOption1 = (data: any) => {
|
|
|
+ option1.value = {
|
|
|
+ tooltip: {},
|
|
|
+ // 还原内部文字
|
|
|
+ title: [
|
|
|
+ {
|
|
|
+ text: data.value + "%",
|
|
|
+ top: "40%",
|
|
|
+ right: "30%",
|
|
|
+ textStyle: {
|
|
|
+ color: "#fff",
|
|
|
+ fontSize: 18,
|
|
|
+ fontWeight: 400,
|
|
|
+ },
|
|
|
},
|
|
|
- tooltip: { show: false },
|
|
|
- });
|
|
|
-
|
|
|
- // 最下边底
|
|
|
- dataArr.series.push({
|
|
|
- name: dataArr.result[0].name,
|
|
|
- z: 30,
|
|
|
- type: "pictorialBar",
|
|
|
- symbolPosition: "start",
|
|
|
- data: diamondData[0],
|
|
|
- symbol: "circle",
|
|
|
- symbolOffset: ["0%", "50%"],
|
|
|
- symbolSize: [15, 12.5],
|
|
|
- itemStyle: {
|
|
|
- color: color[0][0].color,
|
|
|
+ {
|
|
|
+ text: data.data,
|
|
|
+ top: "53%",
|
|
|
+ right: "center",
|
|
|
+ textStyle: {
|
|
|
+ color: "#6F87B1",
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 400,
|
|
|
+ },
|
|
|
},
|
|
|
- tooltip: { show: false },
|
|
|
- });
|
|
|
- setOption(dataArr);
|
|
|
- loading.value = false;
|
|
|
- } catch (e) {
|
|
|
- console.log(e);
|
|
|
- loading.value = false;
|
|
|
- }
|
|
|
-};
|
|
|
-const setOption = (data: any) => {
|
|
|
- option.value = {
|
|
|
- tooltip: {
|
|
|
- trigger: "axis",
|
|
|
- backgroundColor: "rgba(0,0,0,0.7)",
|
|
|
- borderColor: "#000",
|
|
|
- borderWidth: 1,
|
|
|
- textStyle: { color: "#fff" },
|
|
|
- },
|
|
|
- xAxis: {
|
|
|
- axisTick: { show: true },
|
|
|
- axisLine: { lineStyle: { color: "rgba(255,255,255, .2)" } },
|
|
|
- axisLabel: { fontSize: 12, color: "#fff" },
|
|
|
- data: data.xData,
|
|
|
+ ],
|
|
|
+ series: {
|
|
|
+ name: "",
|
|
|
+ type: "pie",
|
|
|
+ radius: ["60%", "85%"],
|
|
|
+ silent: true,
|
|
|
+ clockwise: true,
|
|
|
+ startAngle: 90,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ value: data.value,
|
|
|
+ itemStyle: {
|
|
|
+ color: {
|
|
|
+ type: "linear",
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ x2: 0,
|
|
|
+ y2: 1,
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: baseColorStart,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: baseColorEnd,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 100 - data.value,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ // 圆环底色
|
|
|
+ color: ringColor,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
},
|
|
|
- yAxis: [
|
|
|
+ };
|
|
|
+};
|
|
|
+const setOption2 = (data: any) => {
|
|
|
+ option2.value = {
|
|
|
+ tooltip: {},
|
|
|
+ // 还原内部文字
|
|
|
+ title: [
|
|
|
{
|
|
|
- name: "单位:件",
|
|
|
- nameTextStyle: { color: "#fff", fontSize: 14 },
|
|
|
- nameGap: 25,
|
|
|
- splitLine: { lineStyle: { color: "rgba(255,255,255, .05)" } },
|
|
|
- axisLine: { show: false },
|
|
|
- axisLabel: { fontSize: 12, color: "#fff" },
|
|
|
+ text: data.data,
|
|
|
+ top: "45%",
|
|
|
+ right: "center",
|
|
|
+ textStyle: {
|
|
|
+ color: "#fff",
|
|
|
+ fontSize: 18,
|
|
|
+ fontWeight: 400,
|
|
|
+ },
|
|
|
},
|
|
|
],
|
|
|
- grid: { top: "20%", left: "10%", right: "3%", bottom: "10%" },
|
|
|
- legend: {
|
|
|
- data: data.result.map((item) => item.name),
|
|
|
- textStyle: { fontSize: 12, color: "#fff" },
|
|
|
- itemWidth: 15,
|
|
|
- itemHeight: 10,
|
|
|
- top: "10%",
|
|
|
- right: "20",
|
|
|
+ series: {
|
|
|
+ name: "",
|
|
|
+ type: "pie",
|
|
|
+ radius: ["60%", "85%"],
|
|
|
+ silent: true,
|
|
|
+ clockwise: true,
|
|
|
+ startAngle: 90,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ value: data.value,
|
|
|
+ itemStyle: {
|
|
|
+ color: {
|
|
|
+ type: "linear",
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ x2: 0,
|
|
|
+ y2: 1,
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: baseColorStart,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: baseColorEnd,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
},
|
|
|
- series: data.series,
|
|
|
};
|
|
|
};
|
|
|
onMounted(() => {
|
|
@@ -232,15 +319,14 @@ onMounted(() => {
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
.left-center {
|
|
|
- padding: 10px 20px;
|
|
|
+ padding: 15px 20px;
|
|
|
|
|
|
&-title {
|
|
|
- font-size: 20px;
|
|
|
color: #fff;
|
|
|
}
|
|
|
-
|
|
|
.left-center-content {
|
|
|
height: 260px;
|
|
|
+ padding: 0 10px;
|
|
|
}
|
|
|
}
|
|
|
</style>
|