|
@@ -0,0 +1,462 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="left-top">
|
|
|
|
+ <BorderBox1 class="container"> Content </BorderBox1>
|
|
|
|
+ <div class="flex w-full tab">
|
|
|
|
+ <span :class="{ active: active === '0' }" @click="active = '0'"
|
|
|
|
+ >工单统计</span
|
|
|
|
+ >
|
|
|
|
+ <span
|
|
|
|
+ :class="{ active: active === '2' }"
|
|
|
|
+ @click="active = '2'"
|
|
|
|
+ v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"
|
|
|
|
+ >二次办理统计</span
|
|
|
|
+ >
|
|
|
|
+ <span :class="{ active: active === '1' }" @click="active = '1'"
|
|
|
|
+ >知识库统计</span
|
|
|
|
+ >
|
|
|
|
+ </div>
|
|
|
|
+ <div
|
|
|
|
+ v-if="active === '0'"
|
|
|
|
+ class="flex flex-wrap left-top-content-order"
|
|
|
|
+ v-loading="loading"
|
|
|
|
+ >
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/done_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">办结工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.order.completionCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-rate">
|
|
|
|
+ 办结率:{{ state.order.completionRate }}%
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/wait_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">待受理工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.order.haveToAcceptCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-rate">
|
|
|
|
+ 待受理率:{{ state.order.haveToAcceptRate }}%
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/ex_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">超期工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.order.overTimeCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-rate">
|
|
|
|
+ 超期率:{{ state.order.overTimeRate }}%
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/delay_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">延期工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.order.delayCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-rate">
|
|
|
|
+ 延期率:{{ state.order.delayRate }}%
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/my_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">满意工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.order.satisfiedCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-rate">
|
|
|
|
+ 总满意率:{{ state.order.satisfiedRate }}%
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/provice_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">省工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.order.provinceOrderCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-rate">
|
|
|
|
+ 已办结:{{ state.order.provinceOrderCompletionCount }}件
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div
|
|
|
|
+ v-if="active === '1'"
|
|
|
|
+ class="flex flex-wrap left-top-content-knowledge"
|
|
|
|
+ v-loading="loading"
|
|
|
|
+ >
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_add.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">本月新增知识数量</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.knowledge.todayAddCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 条
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_update.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">本月更新知识数</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp
|
|
|
|
+ :endVal="state.knowledge.thisMonthModifyCount"
|
|
|
|
+ :duration="2"
|
|
|
|
+ />
|
|
|
|
+ </b>
|
|
|
|
+ 条
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_read.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">今日知识阅读量</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.knowledge.todayReadCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 条
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_total.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">知识总数</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp :endVal="state.knowledge.knowledgeCount" :duration="2" />
|
|
|
|
+ </b>
|
|
|
|
+ 条
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div
|
|
|
|
+ v-if="active === '2'"
|
|
|
|
+ class="flex flex-wrap left-top-content-knowledge"
|
|
|
|
+ v-loading="loading"
|
|
|
|
+ >
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/done_order.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">二次办理工单</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp
|
|
|
|
+ :endVal="state.secondHandling.orderCount"
|
|
|
|
+ :duration="2"
|
|
|
|
+ />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_update.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">二次办理超期</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp
|
|
|
|
+ :endVal="state.secondHandling.orderOverdueCount"
|
|
|
|
+ :duration="2"
|
|
|
|
+ />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_read.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">
|
|
|
|
+ 二次办理即将超期工单
|
|
|
|
+ </div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ <CountUp
|
|
|
|
+ :endVal="state.secondHandling.orderSoonOverdueCount"
|
|
|
|
+ :duration="2"
|
|
|
|
+ />
|
|
|
|
+ </b>
|
|
|
|
+ 件
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex left-top-content-item">
|
|
|
|
+ <img src="@/assets/img/home/knowledge_total.png" alt="" />
|
|
|
|
+ <div class="left-top-content-item-text">
|
|
|
|
+ <div class="left-top-content-item-text-title">二次办理满意度</div>
|
|
|
|
+ <div class="left-top-content-item-text-num">
|
|
|
|
+ <b>
|
|
|
|
+ {{ state.secondHandling.satisfactionRate }}
|
|
|
|
+ </b>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+import { defineAsyncComponent, onMounted, reactive, ref, watch } from "vue";
|
|
|
|
+import { knowledge, workOrder, secondHandling } from "@/api/home";
|
|
|
|
+import dayjs from "dayjs";
|
|
|
|
+import { useThemeConfig } from "@/stores/themeConfig";
|
|
|
|
+import { storeToRefs } from "pinia";
|
|
|
|
+
|
|
|
|
+import { BorderBox1 } from "@dataview/datav-vue3";
|
|
|
|
+
|
|
|
|
+const CountUp = defineAsyncComponent(
|
|
|
|
+ () => import("@/components/Count-up/index.vue")
|
|
|
|
+);
|
|
|
|
+
|
|
|
|
+const storesThemeConfig = useThemeConfig();
|
|
|
|
+const { themeConfig } = storeToRefs(storesThemeConfig);
|
|
|
|
+
|
|
|
|
+const active = ref("0");
|
|
|
|
+const props = defineProps({
|
|
|
|
+ dateArray: {
|
|
|
|
+ type: Array,
|
|
|
|
+ default: () => [],
|
|
|
|
+ },
|
|
|
|
+});
|
|
|
|
+const loading = ref(false);
|
|
|
|
+const date = ref([]);
|
|
|
|
+watch(
|
|
|
|
+ () => props.dateArray,
|
|
|
|
+ (val: any) => {
|
|
|
|
+ date.value = val;
|
|
|
|
+ },
|
|
|
|
+ { immediate: true }
|
|
|
|
+);
|
|
|
|
+
|
|
|
|
+watch(
|
|
|
|
+ () => props.dateArray,
|
|
|
|
+ (val: any) => {
|
|
|
|
+ getWorkOrder();
|
|
|
|
+ if (["ZiGong"].includes(themeConfig.value.appScope)) {
|
|
|
|
+ getSecondHandling();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+);
|
|
|
|
+const state = reactive({
|
|
|
|
+ order: {
|
|
|
|
+ completionCount: 0,
|
|
|
|
+ completionRate: 0,
|
|
|
|
+ haveToAcceptCount: 0,
|
|
|
|
+ haveToAcceptRate: 0,
|
|
|
|
+ overTimeCount: 0,
|
|
|
|
+ overTimeRate: 0,
|
|
|
|
+ delayCount: 0,
|
|
|
|
+ delayRate: 0,
|
|
|
|
+ satisfiedCount: 0,
|
|
|
|
+ satisfiedRate: 0,
|
|
|
|
+ provinceOrderCount: 0,
|
|
|
|
+ provinceOrderCompletionCount: 0,
|
|
|
|
+ },
|
|
|
|
+ knowledge: {
|
|
|
|
+ todayAddCount: 0,
|
|
|
|
+ thisMonthModifyCount: 0,
|
|
|
|
+ todayReadCount: 0,
|
|
|
|
+ knowledgeCount: 0,
|
|
|
|
+ },
|
|
|
|
+ secondHandling: {
|
|
|
|
+ orderCount: 0,
|
|
|
|
+ orderOverdueCount: 0,
|
|
|
|
+ orderSoonOverdueCount: 0,
|
|
|
|
+ satisfactionRate: "0%",
|
|
|
|
+ },
|
|
|
|
+});
|
|
|
|
+// 获取工单统计
|
|
|
|
+const getWorkOrder = async () => {
|
|
|
|
+ loading.value = true;
|
|
|
|
+ try {
|
|
|
|
+ const { result } = await workOrder({
|
|
|
|
+ StartTime: dayjs(date.value[0]).format("YYYY-MM-DD"),
|
|
|
|
+ EndTime: dayjs(date.value[1]).format("YYYY-MM-DD"),
|
|
|
|
+ });
|
|
|
|
+ state.order = result;
|
|
|
|
+ loading.value = false;
|
|
|
|
+ } catch (e) {
|
|
|
|
+ console.log(e);
|
|
|
|
+ loading.value = false;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+// 获取知识库统计
|
|
|
|
+const getKnowledge = async () => {
|
|
|
|
+ loading.value = true;
|
|
|
|
+ try {
|
|
|
|
+ const { result } = await knowledge();
|
|
|
|
+ state.knowledge = result;
|
|
|
|
+ loading.value = false;
|
|
|
|
+ } catch (e) {
|
|
|
|
+ console.log(e);
|
|
|
|
+ loading.value = false;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+// 获取二次办理统计
|
|
|
|
+const getSecondHandling = async () => {
|
|
|
|
+ loading.value = true;
|
|
|
|
+ try {
|
|
|
|
+ const { result } = await secondHandling({
|
|
|
|
+ StartTime: dayjs(date.value[0]).format("YYYY-MM-DD"),
|
|
|
|
+ EndTime: dayjs(date.value[1]).format("YYYY-MM-DD"),
|
|
|
|
+ });
|
|
|
|
+ state.secondHandling = result;
|
|
|
|
+ loading.value = false;
|
|
|
|
+ } catch (e) {
|
|
|
|
+ console.log(e);
|
|
|
|
+ loading.value = false;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+onMounted(() => {
|
|
|
|
+ getWorkOrder();
|
|
|
|
+ getKnowledge();
|
|
|
|
+ if (["ZiGong"].includes(themeConfig.value.appScope)) {
|
|
|
|
+ getSecondHandling();
|
|
|
|
+ }
|
|
|
|
+});
|
|
|
|
+</script>
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.left-top {
|
|
|
|
+ padding: 0 30px;
|
|
|
|
+ .container {
|
|
|
|
+ width: 500px;
|
|
|
|
+ height: 200px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .tab {
|
|
|
|
+ span {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ flex: 1;
|
|
|
|
+ height: 50px;
|
|
|
|
+ text-align: center;
|
|
|
|
+ line-height: 50px;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+
|
|
|
|
+ margin-right: 20px;
|
|
|
|
+ background: url("@/assets/img/home/tab_bg.png") no-repeat;
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
+
|
|
|
|
+ &:last-child {
|
|
|
|
+ margin-right: 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.active {
|
|
|
|
+ color: #fff;
|
|
|
|
+ font-size: 18px;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ position: relative;
|
|
|
|
+
|
|
|
|
+ &:after {
|
|
|
|
+ content: "";
|
|
|
|
+ display: block;
|
|
|
|
+ width: 50%;
|
|
|
|
+ height: 30px;
|
|
|
|
+ background: linear-gradient(
|
|
|
|
+ to right,
|
|
|
|
+ rgba(255, 255, 255, 0.2),
|
|
|
|
+ rgba(255, 255, 255, 0.1)
|
|
|
|
+ );
|
|
|
|
+ border-radius: 20px;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 20%;
|
|
|
|
+ left: 25%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &-content {
|
|
|
|
+ &-order {
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ margin-top: 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &-knowledge {
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ margin-top: 40px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &-item {
|
|
|
|
+ width: 50%;
|
|
|
|
+ margin-bottom: 15px;
|
|
|
|
+
|
|
|
|
+ &:last-child {
|
|
|
|
+ margin-right: 0;
|
|
|
|
+ margin-bottom: 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ img {
|
|
|
|
+ width: 50px;
|
|
|
|
+ height: 50px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &-text {
|
|
|
|
+ margin-left: 10px;
|
|
|
|
+
|
|
|
|
+ &-title {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ color: #aaafaf;
|
|
|
|
+ white-space: nowrap;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &-num {
|
|
|
|
+ color: #aaafaf;
|
|
|
|
+
|
|
|
|
+ b {
|
|
|
|
+ font-size: 30px;
|
|
|
|
+ color: #fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &-rate {
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ color: #fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .count-up-wrap {
|
|
|
|
+ display: inline-block;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|