<template>
|
<view class="content">
|
<view
|
v-if="userInfo.isAdmin == 1"
|
class="flex a-center pl-31 pr-31 fs-31 color1 pt-38"
|
>
|
<text class="mr-15">查看范围:</text>
|
<view
|
class="h-77 flex a-center j-between flex1 pl-31 pr-23 border1 br-15 bgColor1"
|
:class="!address && 'color2'"
|
>
|
<view @click.top="selectPopup = true" class="flex1">
|
{{ address || "全部" }}
|
</view>
|
<u-icon
|
class="shrink0"
|
v-if="address"
|
@click="clearAddress"
|
name="close-circle"
|
></u-icon>
|
<image
|
v-else
|
src="/static/down@2x.png"
|
mode="aspectFill"
|
class="w-31 h-31 shrink0"
|
></image>
|
</view>
|
</view>
|
<view class="fs-35 font-bold pt-38 ml-27"> 处理满意率 </view>
|
<view
|
class="ml-29 mr-29 border2 br-15 mt-27 shadow1 flex j-between pl-19 pr-19 pb-35"
|
>
|
<view class="mt-19 flex1">
|
<view class="flex a-center">
|
<view class="w-12 h-12 br-6 border3"></view>
|
<view class="fs-23 ml-15 color3"> 总体满意率 </view>
|
</view>
|
<view class="fs-46 ml-27 mt-12 font-bold">
|
{{ statisticsData.satisfaction.total }}%
|
</view>
|
</view>
|
<view class="flex1 flex j-between ml-50">
|
<view class="fs-23 mt-42 txt-center">
|
<view class="color6"> 本月 </view>
|
<view class="fs-27 font-bold color5 mt-2">
|
{{ statisticsData.satisfaction.month }}%
|
</view>
|
</view>
|
<view class="fs-23 mt-44">
|
<view class="color6"> 同比上月 </view>
|
<view class="txt-aligin-r color4 font-bold mt-4">
|
{{ statisticsData.satisfaction.compare > 0 ? "+" : ""
|
}}{{ statisticsData.satisfaction.compare }}%
|
</view>
|
</view>
|
</view>
|
</view>
|
<view class="fs-35 font-bold mt-38 ml-27"> 诉求单统计 </view>
|
<view class="flex j-between a-center pl-29 pr-29 mt-27">
|
<view class="pl-19 pr-21 shadow1 border2 pt-19 pb-42 flex1 br-15">
|
<view class="flex a-center">
|
<view class="w-12 h-12 br-6 border3"></view>
|
<view class="fs-23 ml-15 color3"> 诉求单量总计 </view>
|
</view>
|
<view class="fs-46 mt-12 font-bold ml-27">
|
{{ statisticsData.demands.total }}
|
</view>
|
<view class="flex j-between mt-21">
|
<view class="fs-23">
|
<view class=""> 本月 </view>
|
<view class="fs-27 font-bold color3 mt-2">
|
{{ statisticsData.demands.month }}
|
</view>
|
</view>
|
<view class="fs-23">
|
<view class=""> 同比上月 </view>
|
<view class="font-bold color8 txt-aligin-r mt-4">
|
{{ statisticsData.demands.compare > 0 ? "+" : ""
|
}}{{ statisticsData.demands.compare }}
|
</view>
|
</view>
|
</view>
|
</view>
|
<view class="pl-19 pr-21 shadow1 border2 pt-19 pb-42 flex1 ml-31 br-15">
|
<view class="flex a-center">
|
<view class="w-12 h-12 br-6 border3"></view>
|
<view class="fs-23 ml-15 color3"> 平均处理时间(天) </view>
|
</view>
|
<view class="fs-46 mt-12 font-bold ml-27">
|
{{ statisticsData.processTime.total }}
|
</view>
|
<view class="flex j-between mt-21">
|
<view class="fs-23">
|
<view class=""> 本月 </view>
|
<view class="fs-27 font-bold color3 mt-2">
|
{{ statisticsData.processTime.month }}
|
</view>
|
</view>
|
<view class="fs-23">
|
<view class=""> 同比上月 </view>
|
<view class="font-bold color4 txt-aligin-r mt-4">
|
{{ statisticsData.processTime.compare > 0 ? "+" : ""
|
}}{{ statisticsData.processTime.compare }}
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
<view class="flex mt-27 gap25 pl-29 pr-29">
|
<view class="flex1 h-154 bgColor2 border4 shadow2 br-19 txt-center">
|
<view class="mt-37 fs-35 color4 font-bold">
|
{{ statisticsData.status.processing }}
|
</view>
|
<view class="fs-23 mt-8 color3"> 正在办理 </view>
|
</view>
|
<view class="flex1 h-154 bgColor3 border4 shadow2 br-19 txt-center">
|
<view class="mt-37 fs-35 color9 font-bold">
|
{{ statisticsData.status.reviewing }}
|
</view>
|
<view class="fs-23 mt-8 color3"> 审核中 </view>
|
</view>
|
<view class="flex1 h-154 bgColor4 border4 shadow2 br-19 txt-center">
|
<view class="mt-37 fs-35 color10 font-bold">
|
{{ statisticsData.status.delayed }}
|
</view>
|
<view class="fs-23 mt-8 color3"> 延期办理 </view>
|
</view>
|
<view class="flex1 h-154 bgColor5 border4 shadow2 br-19 txt-center">
|
<view class="mt-37 fs-35 color11 font-bold">
|
{{ statisticsData.status.completed }}
|
</view>
|
<view class="fs-23 mt-8 color3"> 已办结 </view>
|
</view>
|
</view>
|
<view
|
class="pb-35 ml-29 mr-29 border2 br-15 mt-27 shadow1 flex j-between pl-19 pr-19"
|
>
|
<view class="mt-19 flex1">
|
<view class="flex a-center">
|
<view class="w-12 h-12 br-6 border3"></view>
|
<view class="fs-23 ml-15 color3"> 超时办理 </view>
|
</view>
|
<view class="fs-46 ml-27 mt-12 font-bold">
|
{{ statisticsData.overtime.total }}
|
</view>
|
</view>
|
<view class="flex1 flex j-between ml-50">
|
<view class="fs-23 mt-42 txt-center">
|
<view class="color6"> 本月 </view>
|
<view class="fs-27 font-bold color5 mt-2">
|
{{ statisticsData.overtime.month }}
|
</view>
|
</view>
|
<view class="fs-23 mt-44">
|
<view class="color6"> 同比上月 </view>
|
<view class="txt-aligin-r color4 font-bold mt-4">
|
{{ statisticsData.overtime.compare > 0 ? "+" : ""
|
}}{{ statisticsData.overtime.compare }}
|
</view>
|
</view>
|
</view>
|
</view>
|
<!-- <view class="pb-35 ml-29 mr-29 border2 br-15 mt-27 shadow1 flex j-between pl-19 pr-19">
|
<view class="mt-19 flex1">
|
<view class="flex a-center">
|
<view class="w-12 h-12 br-6 border3"></view>
|
<view class="fs-23 ml-15 color3">
|
办结率
|
</view>
|
</view>
|
<view class="fs-46 ml-27 mt-12 font-bold">
|
77%
|
</view>
|
</view>
|
<view class="flex1 flex j-between ml-50">
|
<view class="fs-23 mt-42 txt-center">
|
<view class="color6">
|
本月
|
</view>
|
<view class="fs-27 font-bold color5 mt-2">
|
88%
|
</view>
|
</view>
|
<view class="fs-23 mt-44">
|
<view class="color6">
|
同比上月
|
</view>
|
<view class="txt-aligin-r color4 font-bold mt-4">
|
+12%
|
</view>
|
</view>
|
</view>
|
</view> -->
|
<view
|
class="mt-27 shadow1 border2 ml-29 mr-29 pt-31 br-15"
|
style="height: 511rpx"
|
>
|
<view class="flex mlr-o tabs mb-40">
|
<view
|
v-for="(item, index) in tabs"
|
:key="index"
|
:class="['tab-item', currentTab === index ? 'active' : '']"
|
@click="handleTabClick(index)"
|
>
|
{{ item }}
|
</view>
|
</view>
|
<view
|
ref="chartRef"
|
id="chart"
|
style="width: 100%; height: 405rpx"
|
></view>
|
</view>
|
<view class="fs-35 font-bold mt-38 ml-27"> 问题类型排名 </view>
|
<view class="ml-29 mr-29 mt-27 shadow1 pt-31 border2 pl-38 pr-38 br-15">
|
<uni-data-select v-model="value1" :localdata="range"></uni-data-select>
|
<view class="fs-23">
|
<view class="flex a-center mb-38" v-for="(item, idx) in typeRankList" :key="idx">
|
<view class="w-130 color3">{{ item.typeName }}</view>
|
<u-line-progress
|
:percentage="item.percent"
|
inactiveColor="#EEEEEE"
|
:activeColor="item.gradientColor"
|
height="38rpx"
|
>
|
<text class="u-percentage-slot pr-19 fs-23">{{ item.count }}</text>
|
</u-line-progress>
|
</view>
|
</view>
|
</view>
|
<view class="fs-35 font-bold mt-38 ml-27"> 评价占比 </view>
|
<view
|
class="ml-29 mr-29 mt-27 shadow1 border2 br-15"
|
style="height: 417rpx"
|
>
|
<view class="flex pl-38 pr-38">
|
<view
|
ref="rateChartRef"
|
id="rateChart"
|
style="width: 288rpx; height: 417rpx"
|
></view>
|
<view style="width: 46rpx"></view>
|
<view class="flex1 pt-54">
|
<view class="mb-27">
|
<view class="flex a-center j-between mb-13">
|
<text class="fs-23">非常满意</text>
|
<text class="fs-23 color12">45%</text>
|
</view>
|
<view class="progress-bar">
|
<view
|
class="progress-inner very-satisfied"
|
style="width: 45%"
|
></view>
|
</view>
|
</view>
|
<view class="mb-27">
|
<view class="flex a-center j-between mb-13">
|
<text class="fs-23">满意</text>
|
<text class="fs-23 color12">20%</text>
|
</view>
|
<view class="progress-bar">
|
<view class="progress-inner satisfied" style="width: 20%"></view>
|
</view>
|
</view>
|
<view class="mb-27">
|
<view class="flex a-center j-between mb-13">
|
<text class="fs-23">一般</text>
|
<text class="fs-23 color12">30%</text>
|
</view>
|
<view class="progress-bar">
|
<view class="progress-inner normal" style="width: 30%"></view>
|
</view>
|
</view>
|
<view class="mb-27">
|
<view class="flex a-center j-between mb-13">
|
<text class="fs-23">不满意</text>
|
<text class="fs-23 color12">5%</text>
|
</view>
|
<view class="progress-bar">
|
<view class="progress-inner unsatisfied" style="width: 5%"></view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
<view class="h-40 safe-b"></view>
|
<!-- 选择服务社区 -->
|
<u-popup
|
:show="selectPopup"
|
round="16rpx"
|
@close="selectPopup = false"
|
:safe-area-inset-bottom="false"
|
@open="openSelectPopup"
|
>
|
<view class="relative pb-40">
|
<image
|
@tap.stop="selectPopup = false"
|
src="@/static/closeImg.png"
|
class="w-35 h-35 absolute"
|
style="right: 31rpx; top: 46rpx"
|
/>
|
<view class="txt-center pt-38 pb-40 fs-35 lh-48 font-bold"
|
>请选择服务社区</view
|
>
|
<view
|
class="flex a-center j-between txt-center py-10 fs-27 font-bold bgColor1"
|
>
|
<view v-if="hasTier(2)" class="flex1">区县</view>
|
<view v-if="hasTier(3)" class="flex1">街道</view>
|
<view v-if="hasTier(4)" class="flex1">社区</view>
|
</view>
|
<view class="mb-20">
|
<picker-view
|
:value="value"
|
@change="bindChange"
|
class="picker-view"
|
immediate-change
|
>
|
<picker-view-column v-if="hasTier(2)">
|
<view
|
class="item"
|
v-for="(item, index) in regionTree"
|
:key="index"
|
>
|
{{ item.name }}
|
</view>
|
</picker-view-column>
|
<picker-view-column v-if="hasTier(3)">
|
<view
|
class="item"
|
v-for="(item, index) in getStreets()"
|
:key="index"
|
>
|
{{ item.name }}
|
</view>
|
</picker-view-column>
|
<picker-view-column v-if="hasTier(4)">
|
<view
|
class="item"
|
v-for="(item, index) in getCommunities()"
|
:key="index"
|
>
|
{{ item.name }}
|
</view>
|
</picker-view-column>
|
</picker-view>
|
</view>
|
<view class="submitBtn" @click="chooseCommunity">确认</view>
|
</view>
|
</u-popup>
|
</view>
|
</template>
|
|
<script>
|
import * as echarts from "echarts";
|
import {
|
getRegionTree,
|
getStaticsPartOne,
|
getStaticsPartTwo,
|
getStaticsPartThree,
|
} from "./service.js";
|
export default {
|
data() {
|
return {
|
userInfo: {},
|
address: "",
|
value: [0, 0, 0],
|
confirmValue: [0, 0, 0],
|
regionTree: [], // 区域树数据
|
value1: 0,
|
selectPopup: false,
|
range: [
|
{
|
value: 0,
|
text: "排名前五",
|
},
|
{
|
value: 1,
|
text: "排名前十",
|
},
|
{
|
value: 2,
|
text: "所有排名",
|
},
|
],
|
chart: null,
|
rateChart: null,
|
tabs: ["近7天", "近15天", "近30天"],
|
currentTab: 0,
|
chartData: {
|
dates: [
|
"2025\n04.17",
|
"2025\n04.18",
|
"2025\n04.19",
|
"2025\n04.20",
|
"2025\n04.21",
|
"2025\n04.22",
|
"2025\n04.23",
|
],
|
demands: [80, 170, 240, 70, 130, 90, 160],
|
completed: [40, 130, 200, 30, 90, 50, 110],
|
},
|
rateData: [
|
{
|
value: 45,
|
name: "非常满意",
|
itemStyle: {
|
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
{
|
offset: 0,
|
color: "#FF8064",
|
},
|
{
|
offset: 1,
|
color: "#FF4934",
|
},
|
]),
|
},
|
},
|
{
|
value: 20,
|
name: "满意",
|
itemStyle: {
|
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
{
|
offset: 0,
|
color: "#05DEE1",
|
},
|
{
|
offset: 1,
|
color: "#02BAC0",
|
},
|
]),
|
},
|
},
|
{
|
value: 30,
|
name: "一般",
|
itemStyle: {
|
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
{
|
offset: 0,
|
color: "#7DC4FF",
|
},
|
{
|
offset: 1,
|
color: "#4791FF",
|
},
|
]),
|
},
|
},
|
{
|
value: 5,
|
name: "不满意",
|
itemStyle: {
|
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
{
|
offset: 0,
|
color: "#FFD364",
|
},
|
{
|
offset: 1,
|
color: "#FEA834",
|
},
|
]),
|
},
|
},
|
],
|
statisticsData: {
|
satisfaction: {
|
total: 0,
|
month: 0,
|
compare: 0,
|
},
|
demands: {
|
total: 0,
|
month: 0,
|
compare: 0,
|
},
|
processTime: {
|
total: 0,
|
month: 0,
|
compare: 0,
|
},
|
status: {
|
processing: 0,
|
reviewing: 0,
|
delayed: 0,
|
completed: 0,
|
},
|
overtime: {
|
total: 0,
|
month: 0,
|
compare: 0,
|
},
|
completionRate: {
|
total: 0,
|
month: 0,
|
compare: 0,
|
},
|
},
|
currentAreaId: '',
|
currentTier: -1,
|
typeRankList: [],
|
};
|
},
|
onLoad() {
|
this.userInfo = uni.getStorageSync("userInfo");
|
this.initRegionData();
|
},
|
mounted() {
|
this.$nextTick(() => {
|
this.initChart();
|
this.initRateChart();
|
});
|
},
|
methods: {
|
clearAddress() {
|
this.address = "";
|
this.value = [0, 0, 0];
|
this.confirmValue = [0, 0, 0];
|
this.currentAreaId = '';
|
this.currentTier = -1;
|
this.getStatisticsData("", -1);
|
this.getChartData(1);
|
this.getTypeRankData();
|
},
|
//初始化区域数据
|
initRegionData() {
|
getRegionTree().then((res) => {
|
if (res.code === 200) {
|
this.regionTree = [{name: '全部', id: 'all', tier: 2, children: []}, ...(res.data || [])];
|
this.value = [0, 0, 0];
|
this.confirmValue = [0, 0, 0];
|
this.address = "全部";
|
this.currentAreaId = '';
|
this.currentTier = -1;
|
this.getStatisticsData("", -1);
|
this.getChartData(1);
|
this.getTypeRankData();
|
}
|
});
|
},
|
// 获取当前选中的区域对象
|
getSelectedRegion() {
|
// 区县
|
const county = this.regionTree[this.value[0]];
|
if (!county || county.id === "all") return { id: "", tier: -1 };
|
// 有街道
|
const streets =
|
county.children && county.children.filter((c) => c && c.tier === 3);
|
if (streets && streets.length) {
|
const street = streets[this.value[1] - 1]; // -1 因为有"全部"选项
|
if (!street || this.value[1] === 0 || street.id === "all")
|
return { id: county.id, tier: county.tier };
|
const communities =
|
street.children && street.children.filter((c) => c && c.tier === 4);
|
if (communities && communities.length) {
|
const community = communities[this.value[2] - 1];
|
if (!community || this.value[2] === 0 || community.id === "all")
|
return { id: street.id, tier: street.tier };
|
return { id: community.id, tier: community.tier };
|
}
|
return { id: street.id, tier: street.tier };
|
}
|
// 区县下直接有社区
|
const communities =
|
county.children && county.children.filter((c) => c && c.tier === 4);
|
if (communities && communities.length) {
|
const community = communities[this.value[1] - 1];
|
if (!community || this.value[1] === 0 || community.id === "all")
|
return { id: county.id, tier: county.tier };
|
return { id: community.id, tier: community.tier };
|
}
|
// 只选了区县
|
return { id: county.id, tier: county.tier };
|
},
|
// 根据value设置地址显示
|
setAddressByValue() {
|
const names = [];
|
const county = this.regionTree[this.value[0]];
|
if (!county) {
|
this.address = "全部";
|
return;
|
}
|
|
// 如果选中区县的全部
|
if (county.id === "all") {
|
this.address = "全部";
|
return;
|
}
|
|
names.push(county.name);
|
|
// 检查是否有街道
|
const streets =
|
county.children && county.children.filter((c) => c && c.tier === 3);
|
if (streets && streets.length) {
|
const street = streets[this.value[1] - 1]; // -1 因为有"全部"选项
|
if (street && street.id !== "all") {
|
names.push(street.name);
|
|
// 检查街道下是否有社区
|
const communities =
|
street.children && street.children.filter((c) => c && c.tier === 4);
|
if (communities && communities.length) {
|
const community = communities[this.value[2] - 1];
|
if (community && community.id !== "all") {
|
names.push(community.name);
|
}
|
}
|
}
|
} else {
|
// 区县下直接有社区
|
const communities =
|
county.children && county.children.filter((c) => c && c.tier === 4);
|
if (communities && communities.length) {
|
const community = communities[this.value[1] - 1];
|
if (community && community.id !== "all") {
|
names.push(community.name);
|
}
|
}
|
}
|
|
this.address = names.join("-");
|
},
|
//选择服务社区
|
chooseCommunity() {
|
this.confirmValue = [...this.value];
|
this.setAddressByValue();
|
const { id, tier } = this.getSelectedRegion();
|
this.currentAreaId = id;
|
this.currentTier = tier;
|
this.selectPopup = false;
|
this.getStatisticsData(id, tier);
|
this.getChartData(this.currentTab + 1);
|
this.getTypeRankData();
|
},
|
// 切换社区
|
bindChange(e) {
|
const newValue = e.detail.value;
|
// 级联重置逻辑
|
if (newValue[0] !== this.value[0]) {
|
newValue[1] = 0;
|
newValue[2] = 0;
|
} else if (newValue[1] !== this.value[1]) {
|
newValue[2] = 0;
|
}
|
this.value = newValue;
|
},
|
openSelectPopup() {
|
this.value = this.confirmValue;
|
},
|
handleTabClick(index) {
|
this.currentTab = index;
|
this.getChartData(index + 1);
|
},
|
initChart() {
|
// 在 H5 端使用 document.getElementById
|
// 在小程序端使用 this.$refs.chartRef
|
const chartDom = document.getElementById("chart") || this.$refs.chartRef;
|
this.chart = echarts.init(chartDom);
|
this.updateChart();
|
},
|
updateChart() {
|
const option = {
|
color: ["#FF7B7B", "#FFB75B"],
|
tooltip: {
|
trigger: "axis",
|
axisPointer: {
|
type: "shadow",
|
},
|
},
|
legend: {
|
data: ["诉求单量", "诉求办结数"],
|
bottom: "0",
|
itemGap: uni.upx2px(60),
|
selectedMode: true,
|
},
|
grid: {
|
left: "3%",
|
right: "4%",
|
bottom: "15%",
|
top: "3%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "category",
|
data: this.chartData.dates,
|
axisLine: {
|
lineStyle: {
|
color: "#E5E5E5",
|
},
|
},
|
axisTick: {
|
show: false,
|
},
|
axisLabel: {
|
color: "#888888",
|
fontSize: uni.upx2px(19),
|
lineHeight: uni.upx2px(23),
|
formatter: function (value) {
|
return value.split("\\n").join("\n");
|
},
|
},
|
},
|
yAxis: {
|
type: "value",
|
splitLine: {
|
lineStyle: {
|
type: "dashed",
|
color: "#fff",
|
},
|
},
|
axisLine: {
|
show: false,
|
},
|
axisTick: {
|
show: false,
|
},
|
},
|
series: [
|
{
|
name: "诉求单量",
|
type: "bar",
|
barWidth: uni.upx2px(38),
|
itemStyle: {
|
borderRadius: [20, 20, 20, 20],
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
{
|
offset: 0,
|
color: "#FF807E",
|
},
|
{
|
offset: 1,
|
color: "#FF4948",
|
},
|
]),
|
},
|
data: this.chartData.demands,
|
},
|
{
|
name: "诉求办结数",
|
type: "line",
|
smooth: true,
|
symbol: "circle",
|
symbolSize: 8,
|
itemStyle: {
|
color: "#FFB75B",
|
borderWidth: 2,
|
borderColor: "#fff",
|
shadowColor: "#FB9A0E",
|
shadowBlur: 8,
|
shadowOffsetY: 4,
|
},
|
lineStyle: {
|
width: 2,
|
curveness: 0.3,
|
},
|
data: this.chartData.completed,
|
},
|
],
|
};
|
this.chart && this.chart.setOption(option);
|
},
|
initRateChart() {
|
const chartDom =
|
document.getElementById("rateChart") || this.$refs.rateChartRef;
|
this.rateChart = echarts.init(chartDom);
|
this.updateRateChart();
|
},
|
updateRateChart() {
|
const option = {
|
tooltip: {
|
trigger: "item",
|
confine: true,
|
// formatter: '{b}: {c}%',
|
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
borderColor: "#FFE0E0",
|
borderWidth: 1,
|
textStyle: {
|
color: "#666666",
|
fontSize: 12,
|
},
|
padding: [8, 12],
|
},
|
series: [
|
{
|
name: "评价占比",
|
type: "pie",
|
radius: ["55%", "100%"],
|
center: ["50%", "50%"],
|
avoidLabelOverlap: false,
|
label: {
|
show: false,
|
},
|
labelLine: {
|
show: false,
|
},
|
emphasis: {
|
scale: false,
|
scaleSize: 0,
|
},
|
data: this.rateData,
|
},
|
],
|
};
|
this.rateChart && this.rateChart.setOption(option);
|
},
|
// 添加获取统计数据的方法
|
async getStatisticsData(areaId = "", tier = -1) {
|
try {
|
const res = await getStaticsPartOne({
|
areaId,
|
tier,
|
});
|
if (res.code === 200) {
|
this.statisticsData = {
|
satisfaction: {
|
total: res.data.satisfactionRate ?? 0,
|
month: res.data.thisMonthSatisfactionRate ?? 0,
|
compare: res.data.lastMonthCompareSatisfactionRate ?? 0,
|
},
|
demands: {
|
total: res.data.allTotal ?? 0,
|
month: res.data.thisMonthTotal ?? 0,
|
compare: res.data.lastMonthCompareTotal ?? 0,
|
},
|
processTime: {
|
total: res.data.averageTime ?? 0,
|
month: res.data.thisMonthAverageTime ?? 0,
|
compare: res.data.lastMonthCompareAverageTime ?? 0,
|
},
|
status: {
|
processing: res.data.nowTransactTotal ?? 0,
|
reviewing: res.data.auditTransactTotal ?? 0,
|
delayed: res.data.postponeTransactTotal ?? 0,
|
completed: res.data.completeTransactTotal ?? 0,
|
},
|
overtime: {
|
total: res.data.overtimeTransactTotal ?? 0,
|
month: res.data.thisMonthOvertimeTransactTotal ?? 0,
|
compare: res.data.lastMonthOvertimeTransactCompareTotal ?? 0,
|
},
|
completionRate: {
|
total: 0,
|
month: 0,
|
compare: 0,
|
},
|
};
|
// 更新图表数据
|
this.updateChart();
|
this.updateRateChart();
|
}
|
} catch (error) {
|
console.error("获取统计数据失败:", error);
|
}
|
},
|
hasTier(tier) {
|
// tier=2: 区县始终有
|
if (tier === 2) return true;
|
// tier=3: 当前区县children里有tier=3
|
if (tier === 3) {
|
const county = this.regionTree[this.value[0]];
|
return (
|
county &&
|
Array.isArray(county.children) &&
|
county.children.some((c) => c && c.tier === 3)
|
);
|
}
|
// tier=4: 当前区县children里有tier=4,或街道children里有tier=4
|
if (tier === 4) {
|
const county = this.regionTree[this.value[0]];
|
if (!county || !Array.isArray(county.children)) return false;
|
// 区县下直接有社区
|
if (county.children.some((c) => c && c.tier === 4)) return true;
|
// 区县下有街道,街道下有社区
|
const street = county.children[this.value[1]];
|
return (
|
street &&
|
Array.isArray(street.children) &&
|
street.children.some((c) => c && c.tier === 4)
|
);
|
}
|
return false;
|
},
|
getStreets() {
|
const county = this.regionTree[this.value[0]];
|
if (!county || !Array.isArray(county.children)) return [];
|
// 只返回tier=3的
|
const streets = county.children.filter((c) => c && c.tier === 3);
|
return streets.length
|
? [{ name: "全部", id: "all", tier: 3, children: [] }, ...streets]
|
: [];
|
},
|
getCommunities() {
|
const county = this.regionTree[this.value[0]];
|
if (!county || !Array.isArray(county.children)) return [];
|
// 区县下直接有社区
|
const communities = county.children.filter((c) => c && c.tier === 4);
|
if (communities.length)
|
return [{ name: "全部", id: "all", tier: 4 }, ...communities];
|
// 区县下有街道,街道下有社区
|
const street = county.children[this.value[1]];
|
if (street && Array.isArray(street.children)) {
|
const comms = street.children.filter((c) => c && c.tier === 4);
|
if (comms.length)
|
return [{ name: "全部", id: "all", tier: 4 }, ...comms];
|
}
|
return [];
|
},
|
async getChartData(timeType = 1) {
|
try {
|
const res = await getStaticsPartTwo({
|
areaId: this.currentAreaId,
|
tier: this.currentTier,
|
timeType
|
});
|
if (res.code === 200 && res.data) {
|
// 转换数据格式
|
const dates = res.data.map(item => item.time.replace(/-/g, '\n').replace(/\n(\d{2})$/, '.$1'));
|
const demands = res.data.map(item => item.allTotal);
|
const completed = res.data.map(item => item.completeTotal);
|
this.chartData = {
|
dates,
|
demands,
|
completed
|
};
|
this.updateChart();
|
}
|
} catch (e) {
|
console.error('获取图表数据失败', e);
|
}
|
},
|
async getTypeRankData() {
|
let rank;
|
if (this.value1 === 0) rank = 5;
|
else if (this.value1 === 1) rank = 10;
|
// value1 === 2 时不传rank
|
const params = {
|
areaId: this.currentAreaId,
|
tier: this.currentTier
|
};
|
if (rank) params.rank = rank;
|
try {
|
const res = await getStaticsPartThree(params);
|
console.log(JSON.stringify(res.data));
|
|
if (res.code === 200 && Array.isArray(res.data)) {
|
// 计算最大值
|
const max = Math.max(...res.data.map(item => item.allTotal), 1);
|
// 处理数据,增加percent字段
|
this.typeRankList = res.data.map((item, idx) => ({
|
typeName: item.name,
|
count: item.allTotal,
|
percent: Math.round(item.allTotal / max * 100),
|
gradientColor: 'linear-gradient(270deg, #FF4934 0%, #FF8064 100%)'
|
}));
|
}
|
} catch (e) {
|
console.error('获取问题类型排名失败', e);
|
}
|
},
|
},
|
watch: {
|
value1() {
|
this.getTypeRankData();
|
}
|
},
|
};
|
</script>
|
|
<style scoped lang="scss">
|
/deep/.uni-select {
|
width: 231rpx;
|
height: 65rpx;
|
margin: 0 auto;
|
margin-bottom: 38rpx;
|
font-size: 27rpx;
|
color: #797f81;
|
border-color: #e5e5e5;
|
border-radius: 33rpx;
|
padding: 0 31rpx 0 40rpx;
|
|
.uni-select__input-text {
|
color: #797f81;
|
}
|
}
|
|
.content {
|
background: linear-gradient(
|
180deg,
|
#ffdcdb 0%,
|
rgba(255, 255, 255, 0) 100rpx,
|
#fff 100%
|
);
|
}
|
|
.gap25 {
|
gap: 25rpx;
|
}
|
|
.tabs {
|
width: 412rpx;
|
background-color: #fff1f1;
|
border-radius: 30rpx;
|
height: 65rpx;
|
line-height: 65rpx;
|
font-size: 27rpx;
|
position: relative;
|
overflow: hidden;
|
}
|
|
.tab-item {
|
color: #797f81;
|
flex: 1;
|
text-align: center;
|
font-weight: 400;
|
height: 54rpx;
|
line-height: 54rpx;
|
border-radius: 27rpx;
|
margin: 6rpx;
|
position: relative;
|
z-index: 1;
|
transform: translateZ(0);
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
&.active {
|
background-color: #fff;
|
color: #ff4948;
|
font-weight: 600;
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
transform: scale(1.02);
|
}
|
}
|
|
.chart-wrapper {
|
background: #fff;
|
border-radius: 20rpx;
|
padding: 20rpx;
|
}
|
|
.color1 {
|
color: #666565;
|
}
|
|
.color2 {
|
color: #c1c1c1;
|
}
|
|
.color3 {
|
color: #666666;
|
}
|
|
.color4 {
|
color: #ff4948;
|
}
|
|
.color5 {
|
color: #696969;
|
}
|
|
.color6 {
|
color: #a4a4a4;
|
}
|
|
.color7 {
|
color: #a7a7a7;
|
}
|
|
.color8 {
|
color: #0fb269;
|
}
|
|
.color9 {
|
color: #ff5600;
|
}
|
|
.color10 {
|
color: #161998;
|
}
|
|
.color11 {
|
color: #08ad60;
|
}
|
|
.color12 {
|
color: #9c9c9e;
|
}
|
|
.bgColor1 {
|
background-color: #fff;
|
}
|
|
.bgColor2 {
|
background-color: #fff1f4;
|
}
|
|
.bgColor3 {
|
background-color: #fff8f4;
|
}
|
|
.bgColor4 {
|
background-color: #f4f5ff;
|
}
|
|
.bgColor5 {
|
background-color: #f1fff8;
|
}
|
|
.border1 {
|
border: 2rpx solid #d9d9d9;
|
}
|
|
.border2 {
|
border: 2rpx solid #ffe0e0;
|
}
|
|
.border3 {
|
border: 4rpx solid #ff4948;
|
box-sizing: border-box;
|
box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(255, 73, 72, 0.5);
|
}
|
|
.border4 {
|
border: 2rpx solid #ffffff;
|
}
|
|
.shadow1 {
|
box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
|
}
|
|
.shadow2 {
|
box-shadow: 0rpx 0rpx 15rpx 0rpx rgba(0, 0, 0, 0.1);
|
}
|
|
.progress-bar {
|
width: 100%;
|
height: 8rpx;
|
background: #eeeeee;
|
border-radius: 4rpx;
|
overflow: hidden;
|
}
|
|
.progress-inner {
|
height: 100%;
|
border-radius: 4rpx;
|
transition: width 0.3s ease-in-out;
|
|
&.very-satisfied {
|
background: linear-gradient(270deg, #ff8064 0%, #ff4934 100%);
|
}
|
|
&.satisfied {
|
background: linear-gradient(270deg, #05dee1 0%, #02bac0 100%);
|
}
|
|
&.normal {
|
background: linear-gradient(270deg, #7dc4ff 0%, #4791ff 100%);
|
}
|
|
&.unsatisfied {
|
background: linear-gradient(270deg, #ffd364 0%, #fea834 100%);
|
}
|
}
|
|
.picker-view {
|
height: 460rpx;
|
font-size: 35rpx;
|
}
|
|
/deep/.picker-view {
|
margin: 0 auto;
|
|
.item {
|
text-align: center;
|
font-family: PingFangSC, PingFang SC;
|
font-weight: 600;
|
font-size: 36rpx;
|
color: #333333;
|
line-height: 50rpx;
|
}
|
}
|
|
.submitBtn {
|
width: calc(100% - 62rpx);
|
margin: 0 31rpx;
|
line-height: 96rpx;
|
text-align: center;
|
background: linear-gradient(270deg, #fc8d55 0%, #ff4948 100%);
|
border-radius: 48rpx;
|
font-weight: 600;
|
font-size: 35rpx;
|
color: #fff;
|
}
|
</style>
|