|
|
|
|
@ -1,287 +1,153 @@
|
|
|
|
|
<template> |
|
|
|
|
<el-dialog |
|
|
|
|
title="单位问题详情" |
|
|
|
|
class="profile-dialog depart-profile" |
|
|
|
|
:title="departInfo.name || '单位问题详情'" |
|
|
|
|
:model-value="modelValue" |
|
|
|
|
@update:model-value="emit('update:modelValue', $event)" |
|
|
|
|
width="85vw" |
|
|
|
|
top="1vh" |
|
|
|
|
style="margin: 1vh auto" |
|
|
|
|
> |
|
|
|
|
<header class="flex center v-center gap"> |
|
|
|
|
<template #header> |
|
|
|
|
<div class="profile-heading"> |
|
|
|
|
<h2>{{ departInfo.name || "单位问题详情" }}</h2> |
|
|
|
|
<p>单位问题详情</p> |
|
|
|
|
</div> |
|
|
|
|
</template> |
|
|
|
|
<header class="profile-toolbar"> |
|
|
|
|
<label>统计范围</label> |
|
|
|
|
<div style="width: 320px"> |
|
|
|
|
<div class="profile-date-field"> |
|
|
|
|
<date-time-range-picker-ext |
|
|
|
|
v-model="time" |
|
|
|
|
format="YYYY-MM-DD" |
|
|
|
|
range-separator="至" |
|
|
|
|
@change="getProfileData" |
|
|
|
|
style="width: 300px" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
<el-button type="primary" @click="getProfileData">查询</el-button> |
|
|
|
|
<el-button class="profile-query-button" type="primary" @click="getProfileData">查询</el-button> |
|
|
|
|
</header> |
|
|
|
|
<el-scrollbar |
|
|
|
|
max-height="calc(98vh - 120px)" |
|
|
|
|
v-loading="loading" |
|
|
|
|
element-loading-text="单位问题详情加载中..." |
|
|
|
|
> |
|
|
|
|
<main> |
|
|
|
|
<el-row class="mb-20" :gutter="20"> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<el-scrollbar max-height="calc(98vh - 180px)" v-loading="loading" element-loading-text="单位问题详情加载中..."> |
|
|
|
|
<main class="profile-content"> |
|
|
|
|
|
|
|
|
|
<div class="profile-grid profile-overview"> |
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>单位情况</h5> |
|
|
|
|
<div class="card-item h-220"> |
|
|
|
|
<el-row class="mb-10"> |
|
|
|
|
<el-col :span="16"> |
|
|
|
|
<div class="row"> |
|
|
|
|
<div class="col col-24"> |
|
|
|
|
<label>单位名称</label> |
|
|
|
|
<span>{{ departInfo.name }}</span> |
|
|
|
|
</div> |
|
|
|
|
<div class="col col-24"> |
|
|
|
|
<label>所长</label> |
|
|
|
|
<span>{{ departInfo.mainRole }}</span> |
|
|
|
|
</div> |
|
|
|
|
<div class="col col-24"> |
|
|
|
|
<label>副所长</label> |
|
|
|
|
<span> |
|
|
|
|
<span |
|
|
|
|
v-for="item in departInfo.deputyRole" |
|
|
|
|
:key="item" |
|
|
|
|
class="mr-10" |
|
|
|
|
>{{ item }}</span |
|
|
|
|
> |
|
|
|
|
</span> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<div class="flex center v-center"> |
|
|
|
|
<img |
|
|
|
|
:src="`${BASE_PATH}/file/stream/${departInfo.departImg}`" |
|
|
|
|
style="max-height: 96px" |
|
|
|
|
v-if="departInfo.departImg1" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
<el-row> |
|
|
|
|
<el-col :span="12"> |
|
|
|
|
<description-pair |
|
|
|
|
label1="民警总人数" |
|
|
|
|
label2="问题涉及民警数" |
|
|
|
|
:value1="departInfo.policeSize" |
|
|
|
|
:value2="departInfo.negativePoliceSize" |
|
|
|
|
size="large" |
|
|
|
|
/> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="12"> |
|
|
|
|
<description-pair |
|
|
|
|
label1="协辅警人数" |
|
|
|
|
label2="问题涉及协辅警数" |
|
|
|
|
:value1="departInfo.auxSize" |
|
|
|
|
:value2="departInfo.negativeAuxSize" |
|
|
|
|
size="large" |
|
|
|
|
/> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<dl class="profile-fields depart-fields"> |
|
|
|
|
<div><dt>所长</dt><dd>{{ departInfo.mainRole || "/" }}</dd></div> |
|
|
|
|
<div><dt>副所长</dt><dd>{{ departInfo.deputyRole?.join("、") || "/" }}</dd></div> |
|
|
|
|
<div><dt>民警总人数</dt><dd>{{ departInfo.policeSize ?? 0 }}</dd></div> |
|
|
|
|
<div><dt>问题涉及民警数</dt><dd>{{ departInfo.negativePoliceSize ?? 0 }}</dd></div> |
|
|
|
|
<div><dt>协辅警人数</dt><dd>{{ departInfo.auxSize ?? 0 }}</dd></div> |
|
|
|
|
<div><dt>问题涉及协辅警数</dt><dd>{{ departInfo.negativeAuxSize ?? 0 }}</dd></div> |
|
|
|
|
</dl> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel problem-panel"> |
|
|
|
|
<h5>问题情况</h5> |
|
|
|
|
<div class="card-item h-220"> |
|
|
|
|
<div class="flex v-center h100"> |
|
|
|
|
<div style="width: 25%" class="text-center"> |
|
|
|
|
<div class="text-primary" style="font-size: 34px"> |
|
|
|
|
{{ negativeInfo.size }} |
|
|
|
|
</div> |
|
|
|
|
<div>问题总数</div> |
|
|
|
|
</div> |
|
|
|
|
<div style="width: 75%"> |
|
|
|
|
<div |
|
|
|
|
class="mb-20" |
|
|
|
|
v-if="negativeInfo.jcj110BusinessSize || negativeInfo.jcj110Size" |
|
|
|
|
> |
|
|
|
|
<description-pair |
|
|
|
|
label1="110接处警量" |
|
|
|
|
label2="110接处警问题数" |
|
|
|
|
:value1="negativeInfo.jcj110BusinessSize" |
|
|
|
|
:value2="negativeInfo.jcj110Size" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
<div |
|
|
|
|
v-if="negativeInfo.jcj122BusinessSize || negativeInfo.jcj122Size" |
|
|
|
|
class="mb-20" |
|
|
|
|
> |
|
|
|
|
<description-pair |
|
|
|
|
label1="122接处警量" |
|
|
|
|
label2="122接处警问题数" |
|
|
|
|
:value1="negativeInfo.jcj122BusinessSize" |
|
|
|
|
:value2="negativeInfo.jcj122Size" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
<div> |
|
|
|
|
<description-pair |
|
|
|
|
label1="执法办案" |
|
|
|
|
label2="执法办案问题数" |
|
|
|
|
:value1="negativeInfo.zfbaBusinessSize" |
|
|
|
|
:value2="negativeInfo.zfbaSize" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<div class="problem-summary"> |
|
|
|
|
<div class="problem-total"> |
|
|
|
|
<span>问题总数</span> |
|
|
|
|
<strong>{{ negativeInfo.size ?? 0 }}</strong> |
|
|
|
|
</div> |
|
|
|
|
<table class="business-table"> |
|
|
|
|
<thead><tr><th>业务类别</th><th>业务量</th><th>问题数</th></tr></thead> |
|
|
|
|
<tbody> |
|
|
|
|
<tr><td>110接处警</td><td>{{ negativeInfo.jcj110BusinessSize ?? 0 }}</td><td>{{ negativeInfo.jcj110Size ?? 0 }}</td></tr> |
|
|
|
|
<tr><td>122接处警</td><td>{{ negativeInfo.jcj122BusinessSize ?? 0 }}</td><td>{{ negativeInfo.jcj122Size ?? 0 }}</td></tr> |
|
|
|
|
<tr><td>执法办案</td><td>{{ negativeInfo.zfbaBusinessSize ?? 0 }}</td><td>{{ negativeInfo.zfbaSize ?? 0 }}</td></tr> |
|
|
|
|
</tbody> |
|
|
|
|
</table> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<h5>问题累计分值</h5> |
|
|
|
|
<div class="flex center card-item wrap h-220"> |
|
|
|
|
<el-progress |
|
|
|
|
type="dashboard" |
|
|
|
|
:percentage="100" |
|
|
|
|
:stroke-width="16" |
|
|
|
|
:width="200" |
|
|
|
|
color="#5B8FF9" |
|
|
|
|
> |
|
|
|
|
<div class="score-progress-body"> |
|
|
|
|
<div> |
|
|
|
|
<div style="font-size: 16px">分数</div> |
|
|
|
|
<div> |
|
|
|
|
<span |
|
|
|
|
class="score-progress_score score-theme text-bold" |
|
|
|
|
style="color: #19257d" |
|
|
|
|
>{{ score }}</span |
|
|
|
|
> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</el-progress> |
|
|
|
|
<div style="width: 100%" class="text-center">累计{{ days }}天分值</div> |
|
|
|
|
</section> |
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>投诉问题</h5> |
|
|
|
|
<div class="complaint-summary"> |
|
|
|
|
<svg class="complaint-icon" viewBox="0 0 48 48" fill="none" aria-hidden="true"> |
|
|
|
|
<path d="M10 8h28a4 4 0 0 1 4 4v20a4 4 0 0 1-4 4H23L12 44v-8h-2a4 4 0 0 1-4-4V12a4 4 0 0 1 4-4Z" stroke="currentColor" stroke-width="2.5" stroke-linejoin="round" /> |
|
|
|
|
<circle cx="16" cy="22" r="2" fill="currentColor" /><circle cx="24" cy="22" r="2" fill="currentColor" /><circle cx="32" cy="22" r="2" fill="currentColor" /> |
|
|
|
|
</svg> |
|
|
|
|
<strong>{{ complaintCount }}</strong> |
|
|
|
|
<span>投诉数量(件)</span> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
<el-row class="mb-20" :gutter="20"> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
</section> |
|
|
|
|
</div> |
|
|
|
|
<div class="profile-grid profile-analysis"> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>问题来源占比</h5> |
|
|
|
|
<div class="card-item"> |
|
|
|
|
<v-charts |
|
|
|
|
style="height: 320px" |
|
|
|
|
:option="problemSourcesPieOptions" |
|
|
|
|
autoresize |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<v-charts class="profile-chart" :option="problemSourcesPieOptions" autoresize /> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>业务类型占比</h5> |
|
|
|
|
<div class="card-item"> |
|
|
|
|
<v-charts |
|
|
|
|
style="height: 320px" |
|
|
|
|
:option="businessTypePieOptions" |
|
|
|
|
autoresize |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<v-charts class="profile-chart" :option="businessTypePieOptions" autoresize /> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>问题涉及方面</h5> |
|
|
|
|
<div class="card-item"> |
|
|
|
|
<v-charts |
|
|
|
|
style="height: 320px" |
|
|
|
|
:option="problemTypePieOptions" |
|
|
|
|
autoresize |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
<el-row class="mb-20" :gutter="20"> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<v-charts class="profile-chart" :option="problemTypePieOptions" autoresize /> |
|
|
|
|
</section> |
|
|
|
|
</div> |
|
|
|
|
<div class="profile-grid profile-analysis"> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>个人问题排名</h5> |
|
|
|
|
<div class="card-item h-300"> |
|
|
|
|
<el-scrollbar max-height="300px"> |
|
|
|
|
<datav-chart-bar |
|
|
|
|
size="small" |
|
|
|
|
:data="policeBarList" |
|
|
|
|
:color="colors" |
|
|
|
|
:labelWidth="60" |
|
|
|
|
/> |
|
|
|
|
<el-empty v-if="policeBarList.length === 0" /> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<el-scrollbar class="ranking-list" height="260px"> |
|
|
|
|
<datav-chart-bar v-if="policeBarList.length" size="small" :data="policeBarList" :color="colors" :label-width="100" label-position="top" /> |
|
|
|
|
<el-empty v-else description="暂无数据" :image-size="70" /> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>问题涉及领导</h5> |
|
|
|
|
<div class="card-item h-300"> |
|
|
|
|
<el-scrollbar max-height="300px"> |
|
|
|
|
<datav-chart-bar |
|
|
|
|
size="small" |
|
|
|
|
:data="policeLeadBarList" |
|
|
|
|
:color="colors" |
|
|
|
|
:labelWidth="60" |
|
|
|
|
/> |
|
|
|
|
<el-empty v-if="policeLeadBarList.length === 0" /> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<el-scrollbar class="ranking-list" height="260px"> |
|
|
|
|
<datav-chart-bar v-if="policeLeadBarList.length" size="small" :data="policeLeadBarList" :color="colors" :label-width="100" label-position="top" /> |
|
|
|
|
<el-empty v-else description="暂无数据" :image-size="70" /> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>突出问题排名</h5> |
|
|
|
|
<div class="card-item h-300"> |
|
|
|
|
<el-scrollbar max-height="300px"> |
|
|
|
|
<datav-chart-bar1 |
|
|
|
|
size="small" |
|
|
|
|
:data="problemTypeBarList" |
|
|
|
|
:color="colors" |
|
|
|
|
labelPosition="top" |
|
|
|
|
/> |
|
|
|
|
<el-empty v-if="problemTypeBarList.length === 0" /> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
</div> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
<div> |
|
|
|
|
<h5>问题变化趋势</h5> |
|
|
|
|
<div class="card-item"> |
|
|
|
|
<v-charts style="height: 320px" :option="barOption" autoresize /> |
|
|
|
|
</div> |
|
|
|
|
<el-scrollbar class="ranking-list" height="260px"> |
|
|
|
|
<datav-chart-bar1 v-if="problemTypeBarList.length" size="small" :data="problemTypeBarList" :color="colors" :label-width="100" label-position="top" /> |
|
|
|
|
<el-empty v-else description="暂无数据" :image-size="70" /> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
</section> |
|
|
|
|
</div> |
|
|
|
|
<h5>问题清单 {{ negativeList.length }}</h5> |
|
|
|
|
<el-table :data="negativeList" height="500"> |
|
|
|
|
<el-table-column label="发现时间" prop="discoveryTime" width="160" /> |
|
|
|
|
<el-table-column label="问题来源" prop="problemSources" width="150" /> |
|
|
|
|
<el-table-column label="业务类别" prop="businessTypeName" width="150" /> |
|
|
|
|
<el-table-column label="问题详情" prop="thingDesc" show-overflow-tooltip /> |
|
|
|
|
<el-table-column |
|
|
|
|
label="核查情况" |
|
|
|
|
prop="checkStatusDesc" |
|
|
|
|
show-overflow-tooltip |
|
|
|
|
/> |
|
|
|
|
<el-table-column label="问题类型" prop="problemType" show-overflow-tooltip /> |
|
|
|
|
<el-table-column label="分值" width="100" align="center"> |
|
|
|
|
<template #default="{ row }"> |
|
|
|
|
<span class="text-danger">{{ row.score }}</span> |
|
|
|
|
</template> |
|
|
|
|
</el-table-column> |
|
|
|
|
<el-table-column label="操作" width="160"> |
|
|
|
|
<template #default="{ row }"> |
|
|
|
|
<el-button type="primary" link @click="handleAction(row)" |
|
|
|
|
>查看详情 |
|
|
|
|
</el-button> |
|
|
|
|
</template> |
|
|
|
|
</el-table-column> |
|
|
|
|
</el-table> |
|
|
|
|
|
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>问题变化趋势</h5> |
|
|
|
|
<v-charts class="trend-chart" :option="barOption" autoresize /> |
|
|
|
|
</section> |
|
|
|
|
<section class="profile-panel"> |
|
|
|
|
<h5>问题清单 <span class="list-count">共 {{ negativeList.length }} 条</span></h5> |
|
|
|
|
<el-table :data="negativeList" max-height="500" class="profile-table"> |
|
|
|
|
<el-table-column label="发现时间" prop="discoveryTime" width="160" /> |
|
|
|
|
<el-table-column label="问题来源" prop="problemSources" width="140" /> |
|
|
|
|
<el-table-column label="业务类别" prop="businessTypeName" width="140" /> |
|
|
|
|
<el-table-column label="问题详情" prop="thingDesc" min-width="220" show-overflow-tooltip /> |
|
|
|
|
<el-table-column label="核查情况" prop="checkStatusDesc" min-width="130" show-overflow-tooltip /> |
|
|
|
|
<el-table-column label="问题类型" prop="problemType" min-width="130" show-overflow-tooltip /> |
|
|
|
|
<el-table-column label="操作" width="110" align="center"> |
|
|
|
|
<template #default="{ row }"> |
|
|
|
|
<el-button type="primary" link @click="handleAction(row)">查看详情</el-button> |
|
|
|
|
</template> |
|
|
|
|
</el-table-column> |
|
|
|
|
</el-table> |
|
|
|
|
</section> |
|
|
|
|
</main> |
|
|
|
|
</el-scrollbar> |
|
|
|
|
|
|
|
|
|
<negative-dialog |
|
|
|
|
v-model="negativeShow" |
|
|
|
|
:id="activeNegativeId" |
|
|
|
|
@close="negativeShow = false" |
|
|
|
|
/> |
|
|
|
|
</el-dialog> |
|
|
|
|
<negative-dialog v-model="negativeShow" :id="activeNegativeId" @close="negativeShow = false" /> |
|
|
|
|
</template> |
|
|
|
|
<script setup> |
|
|
|
|
import vCharts from "vue-echarts"; |
|
|
|
|
import { BASE_PATH } from "@/api/request"; |
|
|
|
|
import { InspectCase } from "@/enums/dictEnums"; |
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
getDepartProfile, |
|
|
|
|
listNegativeMonthly, |
|
|
|
|
} from "@/api/sensitivePerception/profileDepart"; |
|
|
|
|
import { listNegative } from "@/api/work/negative"; |
|
|
|
|
|
|
|
|
|
import moment from "moment"; |
|
|
|
|
|
|
|
|
|
const props = defineProps({ |
|
|
|
|
@ -297,28 +163,18 @@ const time = ref([
|
|
|
|
|
moment().startOf("year").format("YYYY-MM-DD HH:mm:ss"), |
|
|
|
|
moment().format("YYYY-MM-DD HH:mm:ss"), |
|
|
|
|
]); |
|
|
|
|
const colors = [ |
|
|
|
|
{ color: "#5AD8A6", percentage: 40 }, |
|
|
|
|
{ color: "#F6BD16", percentage: 60 }, |
|
|
|
|
{ color: "#E8684A ", percentage: 80 }, |
|
|
|
|
]; |
|
|
|
|
const colors2 = [ |
|
|
|
|
{ color: "var(--success-color)", percentage: 60 }, |
|
|
|
|
{ color: "#DC6231", percentage: 80 }, |
|
|
|
|
{ color: "var(--danger-color)", percentage: 100 }, |
|
|
|
|
]; |
|
|
|
|
const colors = [{ color: "#5B8FF9", percentage: 0 }]; |
|
|
|
|
|
|
|
|
|
// TODO: 投诉数量暂用假数据,后续替换为接口返回值。 |
|
|
|
|
const complaintCount = ref(6); |
|
|
|
|
const loading = ref(false); |
|
|
|
|
|
|
|
|
|
const departInfo = ref({}); |
|
|
|
|
const negativeInfo = ref({}); |
|
|
|
|
|
|
|
|
|
const negativeList = ref([]); |
|
|
|
|
const negativeTotal = ref(0); |
|
|
|
|
const problemTypeBarList = ref([]); |
|
|
|
|
|
|
|
|
|
const score = ref(0); |
|
|
|
|
const days = ref(0); |
|
|
|
|
const problemTypeBarList = ref([]); |
|
|
|
|
|
|
|
|
|
async function getProfileData() { |
|
|
|
|
loading.value = true; |
|
|
|
|
@ -327,40 +183,50 @@ async function getProfileData() {
|
|
|
|
|
beginTime: time.value.length ? time.value[0] : "", |
|
|
|
|
endTime: time.value.length ? time.value[1] : "", |
|
|
|
|
}); |
|
|
|
|
score.value = Math.round(data.score); |
|
|
|
|
days.value = data.days; |
|
|
|
|
|
|
|
|
|
negativeList.value = data.negatives; |
|
|
|
|
departInfo.value = data.departInfo; |
|
|
|
|
negativeInfo.value = data.negativeInfo; |
|
|
|
|
problemSourcesPieOptions.value.series[0].data = data.problemSourcesList; |
|
|
|
|
problemSourcesPieOptions.value.title.text = String(data.negativeInfo.size ?? 0); |
|
|
|
|
businessTypePieOptions.value.series[0].data = data.businessTypeList; |
|
|
|
|
businessTypePieOptions.value.title.text = String(data.negativeInfo.size ?? 0); |
|
|
|
|
problemTypePieOptions.value.series[0].data = data.problemTypeList; |
|
|
|
|
problemTypePieOptions.value.title.text = String(data.negativeInfo.size ?? 0); |
|
|
|
|
|
|
|
|
|
policeBarList.value = data.policeBarList; |
|
|
|
|
policeLeadBarList.value = data.policeLeadBarList; |
|
|
|
|
|
|
|
|
|
radarOption.value.radar.indicator = data.problemTypeRadarIndicator; |
|
|
|
|
radarOption.value.series[0].data[0].value = data.problemTypeRadarData; |
|
|
|
|
|
|
|
|
|
problemTypeBarList.value = data.problemTypeBarList; |
|
|
|
|
loading.value = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const barOption = ref({ |
|
|
|
|
grid: { left: 40, right: 20, top: 30, bottom: 35, containLabel: true }, |
|
|
|
|
tooltip: { trigger: "axis" }, |
|
|
|
|
xAxis: { |
|
|
|
|
type: "category", |
|
|
|
|
data: [], |
|
|
|
|
boundaryGap: false, |
|
|
|
|
axisLabel: { color: "#333" }, |
|
|
|
|
axisLine: { lineStyle: { color: "#dfe6f5" } }, |
|
|
|
|
}, |
|
|
|
|
yAxis: { |
|
|
|
|
type: "value", |
|
|
|
|
name: "问题数", |
|
|
|
|
minInterval: 1, |
|
|
|
|
nameTextStyle: { color: "#333" }, |
|
|
|
|
axisLabel: { color: "#333" }, |
|
|
|
|
splitLine: { lineStyle: { color: "#e8edf6", type: "dashed" } }, |
|
|
|
|
}, |
|
|
|
|
series: [ |
|
|
|
|
{ |
|
|
|
|
data: [], |
|
|
|
|
type: "bar", |
|
|
|
|
color: "#5B8FF9 ", |
|
|
|
|
}, |
|
|
|
|
], |
|
|
|
|
series: [{ |
|
|
|
|
data: [], |
|
|
|
|
type: "line", |
|
|
|
|
symbolSize: 7, |
|
|
|
|
itemStyle: { color: "#5B8FF9" }, |
|
|
|
|
lineStyle: { width: 2 }, |
|
|
|
|
areaStyle: { color: "rgba(91, 143, 249, 0.12)" }, |
|
|
|
|
}], |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
watch( |
|
|
|
|
@ -381,27 +247,6 @@ watch(
|
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const radarOption = ref({ |
|
|
|
|
radar: { |
|
|
|
|
indicator: [], |
|
|
|
|
}, |
|
|
|
|
series: [ |
|
|
|
|
{ |
|
|
|
|
type: "radar", |
|
|
|
|
data: [ |
|
|
|
|
{ |
|
|
|
|
value: [], |
|
|
|
|
areaStyle: { |
|
|
|
|
color: "rgba(255, 145, 124, 0.9)", |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
], |
|
|
|
|
label: { |
|
|
|
|
show: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
], |
|
|
|
|
}); |
|
|
|
|
const problemSourcesPieOptions = ref({ |
|
|
|
|
tooltip: { |
|
|
|
|
trigger: "item", |
|
|
|
|
@ -442,27 +287,35 @@ const problemTypePieOptions = ref({
|
|
|
|
|
const policeBarList = ref([]); |
|
|
|
|
const policeLeadBarList = ref([]); |
|
|
|
|
|
|
|
|
|
function getType(val) { |
|
|
|
|
if (val < 60) { |
|
|
|
|
return "success"; |
|
|
|
|
} |
|
|
|
|
if (val < 80) { |
|
|
|
|
return "warning"; |
|
|
|
|
} |
|
|
|
|
return "danger"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getScoreLabel() { |
|
|
|
|
if (score.value === 0) { |
|
|
|
|
return "无法预测"; |
|
|
|
|
} |
|
|
|
|
if (score.value < 60) { |
|
|
|
|
return "低风险"; |
|
|
|
|
} |
|
|
|
|
if (score.value < 80) { |
|
|
|
|
return "中风险"; |
|
|
|
|
} |
|
|
|
|
return "高风险"; |
|
|
|
|
for (const pieOption of [problemSourcesPieOptions, businessTypePieOptions, problemTypePieOptions]) { |
|
|
|
|
Object.assign(pieOption.value, { |
|
|
|
|
color: ["#5B8FF9", "#5AD8A6", "#F6BD16", "#F6903D", "#6DC8EC"], |
|
|
|
|
title: { |
|
|
|
|
text: "0", |
|
|
|
|
subtext: "问题总数", |
|
|
|
|
left: "30%", |
|
|
|
|
top: "39%", |
|
|
|
|
textAlign: "center", |
|
|
|
|
textStyle: { color: "#162582", fontSize: 22, fontWeight: 700 }, |
|
|
|
|
subtextStyle: { color: "#333", fontSize: 12 }, |
|
|
|
|
}, |
|
|
|
|
legend: { |
|
|
|
|
type: "scroll", |
|
|
|
|
orient: "vertical", |
|
|
|
|
right: 0, |
|
|
|
|
top: "middle", |
|
|
|
|
width: "38%", |
|
|
|
|
textStyle: { color: "#333", fontSize: 13, width: 90, overflow: "truncate" }, |
|
|
|
|
itemWidth: 10, |
|
|
|
|
itemHeight: 10, |
|
|
|
|
pageTextStyle: { color: "#333" }, |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
Object.assign(pieOption.value.series[0], { |
|
|
|
|
center: ["30%", "50%"], |
|
|
|
|
radius: ["45%", "65%"], |
|
|
|
|
label: { show: false }, |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const negativeShow = ref(false); |
|
|
|
|
@ -474,54 +327,181 @@ function handleAction(row) {
|
|
|
|
|
} |
|
|
|
|
</script> |
|
|
|
|
<style lang="scss" scoped> |
|
|
|
|
main { |
|
|
|
|
|
|
|
|
|
:global(.el-dialog.depart-profile) { |
|
|
|
|
--profile-primary: #162582; |
|
|
|
|
--profile-border: #dfe6f5; |
|
|
|
|
padding: 0; |
|
|
|
|
border: 3px solid #243d9b; |
|
|
|
|
border-radius: 8px; |
|
|
|
|
overflow: hidden; |
|
|
|
|
color: #333; |
|
|
|
|
background: #f9faff; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.col { |
|
|
|
|
--label-width: 60px; |
|
|
|
|
:global(.depart-profile .el-dialog__header) { |
|
|
|
|
margin: 0; |
|
|
|
|
padding: 20px 48px 20px 24px; |
|
|
|
|
background: linear-gradient(100deg, #162582, #1c369f); |
|
|
|
|
border-bottom: 2px solid #77bde9; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.score-progress-body { |
|
|
|
|
text-align: center; |
|
|
|
|
font-size: 18px; |
|
|
|
|
|
|
|
|
|
.score-progress_score { |
|
|
|
|
font-size: 50px; |
|
|
|
|
line-height: 70px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.score-progress_title { |
|
|
|
|
font-size: 26px; |
|
|
|
|
line-height: 22px; |
|
|
|
|
} |
|
|
|
|
:global(.depart-profile .el-dialog__body) { padding: 0; color: #333; } |
|
|
|
|
:global(.depart-profile .el-dialog__headerbtn) { top: 10px; right: 10px; } |
|
|
|
|
:global(.depart-profile .el-dialog__close) { color: #fff; } |
|
|
|
|
.profile-heading { |
|
|
|
|
h2 { margin: 0; font-size: 26px; font-weight: 700; color: #fff; line-height: 1.4; } |
|
|
|
|
p { margin: 4px 0 0; font-size: 14px; color: #fff; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.score-theme { |
|
|
|
|
&[type="success"] { |
|
|
|
|
color: var(--success-color); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
&[type="warning"] { |
|
|
|
|
color: #e87749; |
|
|
|
|
.police-profile .profile-heading { text-align: center; } |
|
|
|
|
.profile-toolbar { |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
justify-content: center; |
|
|
|
|
flex-wrap: wrap; |
|
|
|
|
gap: 16px; |
|
|
|
|
padding: 16px 22px 18px; |
|
|
|
|
color: #333; |
|
|
|
|
background: #f9faff; |
|
|
|
|
label { font-size: 16px; font-weight: 500; } |
|
|
|
|
.profile-date-field { width: 340px; max-width: 100%; min-width: 0; } |
|
|
|
|
:deep(.el-date-editor.el-input__wrapper) { |
|
|
|
|
width: 100%; |
|
|
|
|
height: 40px; |
|
|
|
|
box-sizing: border-box; |
|
|
|
|
padding: 0 12px; |
|
|
|
|
border-radius: 4px; |
|
|
|
|
background: #fff; |
|
|
|
|
box-shadow: 0 0 0 1px #dce2ef inset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
&[type="danger"] { |
|
|
|
|
color: var(--danger-color); |
|
|
|
|
:deep(.el-date-editor.is-active) { box-shadow: 0 0 0 1px #162582 inset; } |
|
|
|
|
:deep(.el-range-input) { min-width: 0; color: #333; font-size: 15px; } |
|
|
|
|
:deep(.el-range-separator) { flex: 0 0 24px; padding: 0; color: #333; font-size: 15px; } |
|
|
|
|
:deep(.el-range__icon) { order: 1; margin: 0 0 0 8px; color: #a5b2ce; } |
|
|
|
|
:deep(.el-range__close-icon) { order: 2; margin-left: 4px; } |
|
|
|
|
.profile-query-button { min-width: 88px; height: 40px; font-size: 15px; border-radius: 4px; } |
|
|
|
|
} |
|
|
|
|
.profile-content { |
|
|
|
|
/* 颜色变量定义在真实内容节点,保证弹窗传送后的内容样式生效。 */ |
|
|
|
|
--profile-primary: #162582; |
|
|
|
|
--profile-border: #e2e8f5; |
|
|
|
|
padding: 0 18px 18px; |
|
|
|
|
background: #f9faff; |
|
|
|
|
color: #333; |
|
|
|
|
} |
|
|
|
|
.profile-grid { display: grid; gap: 16px; margin-bottom: 16px; } |
|
|
|
|
.police-profile .profile-overview { grid-template-columns: 1fr 1fr; } |
|
|
|
|
.depart-profile .profile-overview { grid-template-columns: 1.1fr 1fr .8fr; } |
|
|
|
|
.profile-analysis { grid-template-columns: repeat(3, minmax(0, 1fr)); } |
|
|
|
|
.profile-panel { |
|
|
|
|
min-width: 0; |
|
|
|
|
padding: 14px 16px 16px; |
|
|
|
|
border: 1px solid var(--profile-border, #e2e8f5); |
|
|
|
|
border-radius: 6px; |
|
|
|
|
background: linear-gradient(135deg, #f8faff, #fff); |
|
|
|
|
color: #333; |
|
|
|
|
> h5 { |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
gap: 10px; |
|
|
|
|
margin: -14px -16px 16px; |
|
|
|
|
padding: 8px 16px; |
|
|
|
|
background: linear-gradient(90deg, #eef3fc, #f6f9ff); |
|
|
|
|
border-radius: 6px 6px 0 0; |
|
|
|
|
font-size: 18px; |
|
|
|
|
font-weight: 700; |
|
|
|
|
line-height: 1.5; |
|
|
|
|
color: var(--profile-primary, #162582); |
|
|
|
|
&::before { content: ""; width: 4px; height: 20px; border-radius: 2px; background: var(--profile-primary, #162582); flex-shrink: 0; } |
|
|
|
|
} |
|
|
|
|
:deep(.bar-item), :deep(.bar-item-label) { color: #333; font-size: 14px; } |
|
|
|
|
:deep(.bar-item_content) { background: #eaf0fc; } |
|
|
|
|
:deep(.el-empty__description p) { color: #666; } |
|
|
|
|
} |
|
|
|
|
h5 { |
|
|
|
|
margin-bottom: 12px; |
|
|
|
|
.profile-content > .profile-panel { margin-bottom: 16px; } |
|
|
|
|
.profile-content > .profile-panel:last-child { margin-bottom: 0; } |
|
|
|
|
.police-basic { display: flex; align-items: center; gap: 20px; min-height: 240px; } |
|
|
|
|
.police-photo { |
|
|
|
|
width: 140px; |
|
|
|
|
height: 190px; |
|
|
|
|
flex-shrink: 0; |
|
|
|
|
border-radius: 4px; |
|
|
|
|
background: #e5edfc; |
|
|
|
|
border: 1px solid #dbe4f7; |
|
|
|
|
} |
|
|
|
|
.card-item { |
|
|
|
|
background: #f9faff; |
|
|
|
|
padding: 16px; |
|
|
|
|
min-height: 200px; |
|
|
|
|
.photo-placeholder { height: 100%; display: flex; justify-content: center; align-items: center; } |
|
|
|
|
.profile-fields { |
|
|
|
|
flex: 1; |
|
|
|
|
min-width: 0; |
|
|
|
|
margin: 0; |
|
|
|
|
font-size: 15px; |
|
|
|
|
> div { display: flex; gap: 14px; padding: 7px 0; line-height: 1.5; } |
|
|
|
|
dt { width: 72px; flex-shrink: 0; color: #555; } |
|
|
|
|
dd { margin: 0; color: #333; overflow-wrap: anywhere; } |
|
|
|
|
} |
|
|
|
|
.depart-fields { |
|
|
|
|
> div { padding: 9px 0; } |
|
|
|
|
> div:nth-child(2) { margin-bottom: 8px; padding-bottom: 16px; border-bottom: 1px solid #e2e8f5; } |
|
|
|
|
dt { width: auto; flex: 1; } |
|
|
|
|
dd { font-weight: 600; text-align: right; } |
|
|
|
|
} |
|
|
|
|
.problem-summary { display: flex; gap: 16px; align-items: center; min-height: 240px; } |
|
|
|
|
.problem-total { |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
justify-content: center; |
|
|
|
|
flex-direction: column; |
|
|
|
|
align-self: stretch; |
|
|
|
|
flex: 0 0 24%; |
|
|
|
|
gap: 12px; |
|
|
|
|
background: #f3f6fd; |
|
|
|
|
strong { font-size: 54px; line-height: 1.1; color: var(--profile-primary, #162582); } |
|
|
|
|
span { font-size: 15px; color: #333; } |
|
|
|
|
} |
|
|
|
|
.business-table { |
|
|
|
|
width: 100%; |
|
|
|
|
border-collapse: collapse; |
|
|
|
|
font-size: 15px; |
|
|
|
|
text-align: center; |
|
|
|
|
th, td { border-bottom: 1px solid var(--profile-border, #e2e8f5); padding: 13px 8px; } |
|
|
|
|
th { background: #ebeefc; color: var(--profile-primary, #162582); font-weight: 600; white-space: nowrap; } |
|
|
|
|
td { color: #333; } |
|
|
|
|
} |
|
|
|
|
.depart-profile { |
|
|
|
|
.problem-summary { flex-direction: column; align-items: stretch; gap: 14px; } |
|
|
|
|
.problem-total { flex-direction: row; flex-basis: auto; justify-content: flex-start; padding: 8px 0; background: transparent; strong { font-size: 36px; } } |
|
|
|
|
.business-table { th, td { padding: 12px 6px; } } |
|
|
|
|
} |
|
|
|
|
.complaint-summary { |
|
|
|
|
display: flex; |
|
|
|
|
flex-direction: column; |
|
|
|
|
align-items: center; |
|
|
|
|
justify-content: center; |
|
|
|
|
gap: 16px; |
|
|
|
|
min-height: 260px; |
|
|
|
|
strong { font-size: 56px; line-height: 1; color: var(--profile-primary, #162582); } |
|
|
|
|
span { font-size: 16px; color: #333; } |
|
|
|
|
} |
|
|
|
|
.complaint-icon { width: 64px; height: 64px; padding: 10px; box-sizing: border-box; border-radius: 50%; background: #edf3ff; color: #5b8ff9; } |
|
|
|
|
.profile-chart { height: 260px; } |
|
|
|
|
.trend-chart { height: 280px; } |
|
|
|
|
.ranking-list { padding: 4px 0; } |
|
|
|
|
.list-count { font-size: 14px; font-weight: 400; color: #333; } |
|
|
|
|
.profile-table { |
|
|
|
|
--el-table-header-bg-color: #ebeefc; |
|
|
|
|
--el-table-header-text-color: #162582; |
|
|
|
|
--el-table-text-color: #333; |
|
|
|
|
--el-table-border-color: #e2e8f5; |
|
|
|
|
:deep(.el-table__header .el-table__cell) { padding: 12px 0; color: #162582; background: #ebeefc; font-weight: 600; } |
|
|
|
|
:deep(.el-table__cell) { padding: 10px 0; font-size: 14px; color: #333; } |
|
|
|
|
} |
|
|
|
|
.h-220 { |
|
|
|
|
height: 220px; |
|
|
|
|
@media (max-width: 1280px) { |
|
|
|
|
.police-basic { gap: 12px; } |
|
|
|
|
.police-photo { width: 110px; height: 150px; } |
|
|
|
|
.profile-fields { font-size: 14px; > div { gap: 8px; } } |
|
|
|
|
.problem-summary { gap: 10px; } |
|
|
|
|
.problem-total strong { font-size: 42px; } |
|
|
|
|
.business-table { font-size: 14px; th, td { padding: 12px 5px; } } |
|
|
|
|
} |
|
|
|
|
.h-300 { |
|
|
|
|
height: 300px; |
|
|
|
|
@media (max-width: 1000px) { |
|
|
|
|
.police-profile .profile-overview, .depart-profile .profile-overview, .profile-analysis { grid-template-columns: 1fr; } |
|
|
|
|
} |
|
|
|
|
</style> |
|
|
|
|
|