2025-07-22 18:55:04 +08:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { EditOutlined } from '@ant-design/icons-vue';
|
|
|
|
|
import {EchartsUI, type EchartsUIType, useEcharts} from "@vben/plugins/echarts";
|
|
|
|
|
import {onMounted, ref} from "vue";
|
2025-07-23 15:23:57 +08:00
|
|
|
|
import {countsList} from '#/api/property/customerService/centerConsole'
|
2025-07-22 18:55:04 +08:00
|
|
|
|
|
2025-07-23 15:23:57 +08:00
|
|
|
|
const board = ref ({})
|
|
|
|
|
const getBoard = async () => {
|
|
|
|
|
board.value = await countsList();
|
|
|
|
|
}
|
2025-07-22 18:55:04 +08:00
|
|
|
|
const xAxisData = ref<any[]>([]);
|
|
|
|
|
const seriesData = ref<any[]>([]);
|
2025-07-23 15:23:57 +08:00
|
|
|
|
|
|
|
|
|
// 工单计数
|
|
|
|
|
const workOrderCount = ref<EchartsUIType>();
|
|
|
|
|
const { renderEcharts: renderWorkOrderCount } = useEcharts(workOrderCount);
|
|
|
|
|
async function fetchWorkOrderCount() {
|
|
|
|
|
xAxisData.value = board.value.recentWeekWorkOrders
|
|
|
|
|
console.log(xAxisData.value)
|
|
|
|
|
renderWorkOrderCount({
|
2025-07-22 18:55:04 +08:00
|
|
|
|
tooltip: { trigger: 'axis' },
|
|
|
|
|
xAxis: {
|
|
|
|
|
type: 'category',
|
|
|
|
|
boundaryGap: false,
|
2025-07-23 15:23:57 +08:00
|
|
|
|
data: ['06-17周二', '06-17周二', '06-17周二', '06-17周二', '06-17周二', '06-17周二', '06-17周二']
|
|
|
|
|
},
|
|
|
|
|
yAxis: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
name: '近一周工单数',
|
2025-07-22 18:55:04 +08:00
|
|
|
|
},
|
|
|
|
|
series: [
|
|
|
|
|
{
|
2025-07-23 15:23:57 +08:00
|
|
|
|
data: [6, 2, 0, 1, 0, 0, 1],
|
2025-07-22 18:55:04 +08:00
|
|
|
|
type: 'line',
|
2025-07-23 15:23:57 +08:00
|
|
|
|
areaStyle: {},
|
2025-07-22 18:55:04 +08:00
|
|
|
|
smooth: true,
|
2025-07-23 15:23:57 +08:00
|
|
|
|
}
|
|
|
|
|
]
|
2025-07-22 18:55:04 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
2025-07-23 15:23:57 +08:00
|
|
|
|
|
|
|
|
|
// 满意度指数
|
|
|
|
|
const satisfactionLevel = ref<EchartsUIType>();
|
|
|
|
|
const { renderEcharts: renderSatisfactionLevel } = useEcharts(satisfactionLevel);
|
|
|
|
|
async function fetchSatisfactionLevel() {
|
|
|
|
|
renderSatisfactionLevel({
|
|
|
|
|
title: {text: '满意度指数',left: '18px'},
|
|
|
|
|
tooltip: { trigger: 'item'},
|
|
|
|
|
radar: {
|
|
|
|
|
indicator: [
|
|
|
|
|
{name: '1星', max: 1000},
|
|
|
|
|
{name: '2星', max: 1000},
|
|
|
|
|
{name: '3星', max: 1000},
|
|
|
|
|
{name: '4星', max: 1000},
|
|
|
|
|
{name: '5星', max: 1000},
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
series: [
|
|
|
|
|
{
|
|
|
|
|
type: 'radar',
|
|
|
|
|
name: '满意度指数',
|
|
|
|
|
data: [
|
|
|
|
|
{
|
|
|
|
|
value: [500, 400, 800, 600, 400],
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 近半年工单数
|
|
|
|
|
const orderNumber = ref<EchartsUIType>();
|
|
|
|
|
const { renderEcharts: renderOrderNumber } = useEcharts(orderNumber);
|
|
|
|
|
async function fetchOrderNumber() {
|
|
|
|
|
renderOrderNumber({
|
|
|
|
|
title: {text: '近半年工单数',left: '18px'},
|
|
|
|
|
legend: {},
|
|
|
|
|
tooltip: { trigger: 'axis' },
|
|
|
|
|
dataset: {
|
|
|
|
|
source: [
|
|
|
|
|
['product', '物业', '入驻员工'],
|
|
|
|
|
['2025-01', 2, 5.8],
|
|
|
|
|
['2025-02', 10.1, 7.4],
|
|
|
|
|
['2025-03', 6.4, 5.2],
|
|
|
|
|
['2025-04', 3.3, 5.8],
|
|
|
|
|
['2025-05', 8.1, 7.4],
|
|
|
|
|
['2025-06', 6.4, 5.2],
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
xAxis: { type: 'category' },
|
|
|
|
|
yAxis: {},
|
|
|
|
|
series: [{ type: 'bar' }, { type: 'bar' }]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 工单类型分类占比
|
|
|
|
|
const orderTyper = ref<EchartsUIType>();
|
|
|
|
|
const { renderEcharts: renderOrderTyper } = useEcharts(orderTyper);
|
|
|
|
|
async function fetchOrderTyper() {
|
|
|
|
|
renderOrderTyper({
|
|
|
|
|
title: {text: '工单类型分类占比',left: '18px',top: '18px'},
|
|
|
|
|
tooltip: {
|
|
|
|
|
trigger: 'item'
|
|
|
|
|
},
|
|
|
|
|
legend: {
|
|
|
|
|
top: '40%',
|
|
|
|
|
right: '10%',
|
|
|
|
|
orient: 'vertical',
|
|
|
|
|
icon: 'circle',
|
|
|
|
|
itemWidth: 8,
|
|
|
|
|
itemHeight: 8
|
|
|
|
|
},
|
|
|
|
|
series: [
|
|
|
|
|
{
|
|
|
|
|
type: 'pie',
|
|
|
|
|
center: ['40%', '55%'],
|
|
|
|
|
radius: ['40%', '70%'],
|
|
|
|
|
label: {
|
|
|
|
|
show: true,
|
|
|
|
|
position: 'center',
|
|
|
|
|
formatter: '员工单数量\n{num|56个}',
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
color: 'gray',
|
|
|
|
|
rich: {
|
|
|
|
|
num: {
|
|
|
|
|
fontSize: 18,
|
|
|
|
|
fontWeight: 'bolder',
|
|
|
|
|
color:'black',
|
|
|
|
|
padding: [10, 0, 0, 0],
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
avoidLabelOverlap: false,
|
|
|
|
|
labelLine: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
data: [
|
|
|
|
|
{ value: 1048, name: 'Search Engine' },
|
|
|
|
|
{ value: 735, name: 'Direct' },
|
|
|
|
|
{ value: 580, name: 'Email' },
|
|
|
|
|
{ value: 484, name: 'Union Ads' },
|
|
|
|
|
{ value: 300, name: 'Video Ads' }
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-22 18:55:04 +08:00
|
|
|
|
onMounted(async () => {
|
2025-07-23 15:23:57 +08:00
|
|
|
|
await getBoard()
|
|
|
|
|
await fetchWorkOrderCount()
|
|
|
|
|
await fetchSatisfactionLevel()
|
|
|
|
|
await fetchOrderNumber()
|
|
|
|
|
await fetchOrderTyper()
|
2025-07-22 18:55:04 +08:00
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="panel">
|
|
|
|
|
|
|
|
|
|
<div class="bulletin-board">
|
|
|
|
|
<div class="bulletin-board-title">工单看板</div>
|
|
|
|
|
<div class="bulletin-board-content">
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>工单总数:</div>
|
2025-07-23 15:23:57 +08:00
|
|
|
|
<div>{{ board.workOrdersTotal }}</div>
|
2025-07-22 18:55:04 +08:00
|
|
|
|
<div style="color: #1890FF">点击前往工单池</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="icon-edit"><EditOutlined /></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>待派工单数:</div>
|
2025-07-23 15:23:57 +08:00
|
|
|
|
<div>{{ board.notWorkOrdersTotal }}</div>
|
2025-07-22 18:55:04 +08:00
|
|
|
|
<div style="color: #1890FF">点击前往工单待办</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="icon-edit"><EditOutlined /></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>未办结超时工单:</div>
|
2025-07-23 15:23:57 +08:00
|
|
|
|
<div>{{ board.novertimeOrdersTotal }}</div>
|
|
|
|
|
<div>处理中的工单数:<span style="color: green">{{ board.inHandOrdersTotal }}</span></div>
|
2025-07-22 18:55:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="icon-edit"><EditOutlined /></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>当月工单超时率:</div>
|
2025-07-23 15:23:57 +08:00
|
|
|
|
<div>{{ board.novertimeOrdersRate }}%</div>
|
|
|
|
|
<div>超时工单数:<span style="color: red">{{ board.outTimeOrdersTotal }}</span></div>
|
2025-07-22 18:55:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="icon-edit"><EditOutlined /></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>当月满意度:</div>
|
2025-07-23 15:23:57 +08:00
|
|
|
|
<div>{{ board.monthoSatisfaction }}%</div>
|
|
|
|
|
<div>满意度:{{ board.satisfaction }}</div>
|
2025-07-22 18:55:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="icon-edit"><EditOutlined /></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chart">
|
|
|
|
|
<div class="chart-one">
|
|
|
|
|
<div>
|
2025-07-23 15:23:57 +08:00
|
|
|
|
<div>
|
|
|
|
|
<div style="font-size: 20px;font-weight: bold;margin-bottom: 20px;color: #464646">工单计数</div>
|
|
|
|
|
<div style="margin-left: 20px;line-height: 30px">
|
|
|
|
|
<div>累计处理工单数</div>
|
|
|
|
|
<div>12</div>
|
|
|
|
|
<div>累计回复数</div>
|
|
|
|
|
<div>2</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-07-22 18:55:04 +08:00
|
|
|
|
<EchartsUI
|
2025-07-23 15:23:57 +08:00
|
|
|
|
ref="workOrderCount"
|
|
|
|
|
height="400px"
|
2025-07-22 18:55:04 +08:00
|
|
|
|
width="100%"
|
2025-07-23 15:23:57 +08:00
|
|
|
|
style="background: #fff; border-radius: 8px;padding-top: 30px"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<EchartsUI
|
|
|
|
|
ref="satisfactionLevel"
|
|
|
|
|
height="400px"
|
|
|
|
|
width="100%"
|
|
|
|
|
style="background: #fff; border-radius: 8px;padding-top: 18px"
|
2025-07-22 18:55:04 +08:00
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chart-two">
|
|
|
|
|
<div>
|
|
|
|
|
<EchartsUI
|
2025-07-23 15:23:57 +08:00
|
|
|
|
ref="orderNumber"
|
|
|
|
|
height="400px"
|
|
|
|
|
width="100%"
|
|
|
|
|
style="background: #fff; border-radius: 8px;padding-top: 18px"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<EchartsUI
|
|
|
|
|
ref="orderTyper"
|
|
|
|
|
height="400px"
|
2025-07-22 18:55:04 +08:00
|
|
|
|
width="100%"
|
|
|
|
|
style="background: #fff; border-radius: 8px"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.panel{
|
|
|
|
|
width: 100%;
|
|
|
|
|
padding: 40px;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
|
|
.bulletin-board{
|
|
|
|
|
|
|
|
|
|
.bulletin-board-title{
|
|
|
|
|
font-size: 25px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
}
|
|
|
|
|
.bulletin-board-content{
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(5, 1fr);
|
|
|
|
|
gap: 40px;
|
|
|
|
|
|
|
|
|
|
> div{
|
|
|
|
|
height: auto;
|
|
|
|
|
background-color: #FFFFFF;
|
|
|
|
|
padding: 18px;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
|
|
> div:first-child {
|
|
|
|
|
line-height: 32px;
|
|
|
|
|
|
|
|
|
|
div:nth-child(2) {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.icon-edit{
|
|
|
|
|
font-size: 30px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.chart{
|
|
|
|
|
|
|
|
|
|
.chart-one{
|
|
|
|
|
margin-top:40px;
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 2fr 1fr;
|
|
|
|
|
gap: 40px;
|
2025-07-23 15:23:57 +08:00
|
|
|
|
|
|
|
|
|
>div:first-child{
|
|
|
|
|
background-color: #FFFFFF;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 1fr 6fr;
|
|
|
|
|
|
|
|
|
|
>div:first-child{
|
|
|
|
|
padding: 18px 0 0 18px;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-22 18:55:04 +08:00
|
|
|
|
}
|
|
|
|
|
.chart-two{
|
|
|
|
|
margin-top:40px;
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
gap: 40px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|