Browse Source

fit: 单位画像、个人画像

main
wxc 1 year ago
parent
commit
b4e097a02d
  1. 14
      src/api/sensitivePerception/profileDepart.ts
  2. 22
      src/components/datav/chart-bar.vue
  3. 330
      src/views/sensitivePerception/DepartNegative.vue
  4. 342
      src/views/sensitivePerception/PoliceNegative.vue

14
src/api/sensitivePerception/profileDepart.ts

@ -0,0 +1,14 @@
import request from "@/api/request";
export function listDepartNegative(query) {
return request.get({
url: `/profile/depart`,
query
});
}
export function getDepartProfile(departId) {
return request.get({
url: `/profile/depart/${departId}`
});
}

22
src/components/datav/chart-bar.vue

@ -6,7 +6,7 @@
<div>
<div
class="flex v-center bar-item between"
v-for="item in data"
v-for="item in data.sort((a, b) => b.value - a.value)"
:size="size"
>
<span class="bar-item-name mr-10">{{ item.label }}</span>
@ -84,14 +84,21 @@ function getColor(val) {
if (props.color instanceof String) {
return props.color;
}
if (val > 0.8) {
return "linear-gradient(270deg, #63e700 0%, #19674c 100%)";
if (props.color instanceof Array) {
const colors = [...props.color]
colors.reduce((a, b) => b.percentage - a.percentage)
console.log(colors)
for (let i = 0; i < colors.length; i++) {
if (val > colors[0].percentage) {
return colors[0].color;
}
if (val >= 0.7) {
return "linear-gradient( 270deg, #FFB90E 0%, #71501D 100%)";
}
return "linear-gradient( 270deg, #FB002D 0%, #822232 100%)";
}
return "linear-gradient(270deg, #63e700 0%, #19674c 100%)";
// if (val >= 0.7) {
// return "linear-gradient( 270deg, #FFB90E 0%, #71501D 100%)";
// }
// return "linear-gradient( 270deg, #FB002D 0%, #822232 100%)";
}
</script>
<style lang="scss" scoped>
@ -123,7 +130,6 @@ function getColor(val) {
width: 0;
height: 9px;
background: linear-gradient(270deg, #63e700 0%, #19674c 100%);
box-shadow: 1px 0 0px 0px #020b5f;
transition: width 0.3s;
}
}

330
src/views/sensitivePerception/DepartNegative.vue

@ -4,24 +4,20 @@
<el-form :label-width="114">
<el-row>
<el-col :span="6">
<el-form-item label="单位名称">
<el-input
placeholder="请输入"
v-model="query.name"
<el-form-item label="三级单位">
<depart-tree-select
v-model="query.departId"
:check-strictly="false"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="单位类型">
<el-input
placeholder="请输入"
v-model="query.six"
<el-form-item label="统计时间">
<date-time-range-picker-ext
v-model="query.crtTime"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="统计时间"> </el-form-item>
</el-col>
</el-row>
</el-form>
<div class="mb-25 flex end">
@ -38,56 +34,101 @@
</header>
<div class="table-container">
<el-table :data="list">
<el-table-column label="单位名称" prop="" />
<el-table-column label="主要责任人" prop="" />
<el-table-column label="民警人数" prop="" />
<el-table-column label="协辅警人数" prop="" />
<el-table-column label="查实问题涉及人数" prop="" width="180" />
<el-table-column label="单位名称">
<template #default="{ row }">
<span
>{{ row.parentDepartName }}/{{
row.departName
}}</span
>
</template>
</el-table-column>
<el-table-column
label="查实问题数"
prop="departName"
width="120"
label="民警人数"
prop="policeSize"
align="center"
width="160"
/>
<el-table-column
label="风险指数"
prop="fxzs"
width="120"
label="协辅警人数"
prop="auxSize"
align="center"
width="160"
/>
<el-table-column
label="查实问题涉及人数"
prop="verifyPoliceSize"
align="center"
width="160"
/>
<el-table-column
label="查实问题数"
prop="verifySize"
align="center"
width="160"
/>
<el-table-column label="操作" width="160">
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" link @click="show = true"
>查看详情</el-button
<el-button
type="primary"
link
@click="handleShowProfile(row)"
>问题画像</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-8">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[9, 18, 36]"
v-model:page-size="query.size"
v-model:current-page="query.current"
layout="total, sizes, prev, pager, next"
:total="total"
v-if="list.length"
>
</el-pagination>
</div>
</div>
<el-dialog title="单位问题画像" v-model="show" width="85vw" top="2vh">
<header class="flex center v-center gap">
<label for="">统计范围</label>
<label>统计范围</label>
<div style="width: 320px">
<date-time-range-picker-ext
v-model="query.crtTime"
style="width: 300px"
/>
</div>
<el-button type="primary">查询</el-button>
</header>
<main>
<main v-loading="loading">
<el-row>
<el-col :span="8">
<h5>单位情况</h5>
<div class="row">
<div class="col col-24">
<label>单位名称</label>
<span>{{}}</span>
<span>{{ departInfo.name }}</span>
</div>
<div class="col col-24">
<label>所长</label>
<span>{{}}</span>
<span>{{ departInfo.mainRole }}</span>
</div>
<div class="col col-24">
<label>副所长</label>
<span>{{}}</span>
<span>
<span
v-for="item in departInfo.deputyRole"
:key="item"
>{{ item }}</span
>
</span>
</div>
</div>
<el-row>
@ -95,8 +136,8 @@
<description-pair
label1="民警总人数"
label2="问题涉及民警数"
value1="132"
value2="21"
:value1="departInfo.policeSize"
:value2="departInfo.policeSize"
size="large"
/>
</el-col>
@ -104,8 +145,8 @@
<description-pair
label1="协辅警人数"
label2="问题涉及协辅警数"
value1="132"
value2="21"
:value1="departInfo.auxSize"
:value2="departInfo.policeSize"
size="large"
/>
</el-col>
@ -116,7 +157,7 @@
<el-row>
<el-col :span="6" class="text-center">
<div class="text-primary" style="font-size: 34px">
51
{{ activeRow.verifySize }}
</div>
<div>问题总数</div>
</el-col>
@ -152,11 +193,25 @@
:width="250"
color="#DC6231"
>
<div>
<span style="">78</span>
<div style="line-height: 64px" class="mt-40">
<span
style="
font-weight: 600;
font-size: 60px;
color: #e87749;
"
>78</span
>
<span style="font-size: 18px; color: #999"
></span
>
</div>
<div style="font-size: 14px" class="mb-10">
分险指标值
</div>
<div style="color: #e87749; font-size: 28px">
中风险
</div>
<div>分险指标值</div>
<div>中风险</div>
</el-progress>
</div>
</el-col>
@ -164,40 +219,231 @@
<el-row>
<el-col :span="8">
<h5>问题来源占比</h5>
<v-charts
style="height: 320px"
:option="pieOptions"
autoresize
/>
</el-col>
<el-col :span="8">
<h5>业务类型占比</h5>
<v-charts
style="height: 320px"
:option="pieOptions"
autoresize
/>
</el-col>
<el-col :span="8">
<h5>风险问题构成</h5>
<v-charts
style="height: 320px"
:option="radarOption"
autoresize
/>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<h5>个人问题排名</h5>
<datav-chart-bar :data="barList" :color="colors" />
</el-col>
<el-col :span="8">
<h5>突出问题排名</h5>
<datav-chart-bar :data="barList" />
</el-col>
<el-col :span="8">
<h5>单位问题标签</h5>
<datav-chart-bar :data="barList" />
</el-col>
</el-row>
<h5>问题变化趋势</h5>
<v-charts style="height: 320px" :option="barOption" autoresize />
<div></div>
<h5>问题清单</h5>
<div></div>
<el-table :data="negativeList">
<el-table-column label="发现时间" prop="discoveryTime" />
<el-table-column label="问题来源" prop="problemSources" />
<el-table-column label="业务类别" prop="businessTypeName" />
<el-table-column label="涉及单位" prop="involveDepartName" />
<el-table-column
label="核查情况"
prop="checkStatusName"
width="180"
align="center"
/>
</el-table>
<div class="flex end mt-8">
<el-pagination
@size-change="getNegativeList"
@current-change="getNegativeList"
:current-page="negativeQuery.current"
:page-sizes="[10, 20, 50]"
:page-size="negativeQuery.size"
v-model:current-page="negativeQuery.current"
layout="total, sizes, prev, pager, next"
:total="negativeTotal"
>
</el-pagination>
</div>
</main>
</el-dialog>
</template>
<script lang="ts" setup>
import vCharts from "vue-echarts";
import {
listDepartNegative,
getDepartProfile,
} from "@/api/sensitivePerception/profileDepart";
import { listNegative } from "@/api/work/negative";
import { InspectCase } from "@/enums/dictEnums";
const query = ref({
current: 1,
size: 10,
});
const list = ref<any[]>([]);
const total = ref(0);
function getList() {
listDepartNegative(query.value).then((data) => {
list.value = data.records;
total.value = data.total;
});
}
function reset() {
query.value = {
current: 1,
size: 10,
};
getList();
}
onMounted(() => {
getList();
});
const activeRow = ref({});
const show = ref(false);
const departInfo = ref({});
const loading = ref(false);
const negativeQuery = ref({
checkStatusList: [InspectCase.TRUE, InspectCase.TRUE],
});
const negativeList = ref([]);
const negativeTotal = ref(0);
async function handleShowProfile(row) {
activeRow.value = row;
loading.value = true;
show.value = true;
negativeQuery.value.involveDepartId = row.departId;
getNegativeList();
const data = await getDepartProfile(row.departId);
departInfo.value = data.departInfo;
loading.value = false;
}
function getNegativeList() {
listNegative(negativeQuery.value).then((data) => {
negativeList.value = data.records;
negativeTotal.value = data.total;
});
}
const colors = [
{ color: "#f56c6c", percentage: 20 },
{ color: "#e6a23c", percentage: 40 },
{ color: "#5cb87a", percentage: 60 },
{ color: "#1989fa", percentage: 80 },
{ color: "#6f7ad3", percentage: 100 },
];
const barList = [
{
label: "张三",
value: 67,
},
{
label: "李四",
value: 80,
},
{
label: "王五",
value: 40,
},
{
label: "王五",
value: 40,
},
{
label: "王五",
value: 10,
},
];
const pieOptions = computed(() => {
return {
series: [
{
type: "pie",
radius: ["40%", "70%"],
data: [
{ value: 311, name: "慢作为" },
{ value: 735, name: "意见建议" },
{ value: 580, name: "违法违纪违规" },
{ value: 484, name: "乱作为" },
{ value: 300, name: "其他" },
{ value: 300, name: "不作为" },
],
},
],
};
});
const radarOption = {
radar: {
// shape: 'circle',
indicator: [
{ name: "内部管理", max: 6500 },
{ name: "涉及监督", max: 6500 },
{ name: "记录作风", max: 30000 },
{ name: "警保卫工作", max: 38000 },
{ name: "执法办案", max: 52000 },
{ name: "专项工作", max: 25000 },
],
},
series: [
{
name: "Budget vs spending",
type: "radar",
data: [
{
value: [4200, 3000, 20000, 35000, 50000, 18000],
},
],
},
],
};
const show = ref(true);
const barOption = {
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: "bar",
},
],
};
</script>
<style lang="scss" scoped>
</style>

342
src/views/sensitivePerception/PoliceNegative.vue

@ -0,0 +1,342 @@
<template>
<div class="container">
<header>
<el-form :label-width="114">
<el-row>
<el-col :span="6">
<el-form-item label="所在单位">
<depart-tree-select
v-model="query.departId"
:check-strictly="false"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="统计时间">
<date-time-range-picker-ext
v-model="query.crtTime"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="mb-25 flex end">
<div>
<el-button type="primary" @click="getList">
<template #icon>
<icon name="el-icon-Search" />
</template>
查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</div>
</header>
<div class="table-container">
<el-table :data="list">
<el-table-column label="姓名" prop="name" />
<el-table-column label="性别" />
<el-table-column label="职务" prop="" />
<el-table-column label="警号" prop="empNo" />
<el-table-column label="任职年限" prop="" />
<el-table-column label="单位名称" prop="policeSize" />
<el-table-column
label="查实问题数"
prop="verifySize"
width="120"
/>
<el-table-column label="操作" width="160">
<template #default="{ row }">
<el-button type="primary" link @click="show = true"
>问题画像</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-8">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[9, 18, 36]"
v-model:page-size="query.size"
v-model:current-page="query.current"
layout="total, sizes, prev, pager, next"
:total="total"
v-if="list.length"
>
</el-pagination>
</div>
</div>
<el-dialog title="单位问题画像" v-model="show" width="85vw" top="2vh">
<header class="flex center v-center gap">
<label>统计范围</label>
<div style="width: 320px">
<date-time-range-picker-ext v-model="query.crtTime" style="width: 300px" />
</div>
<el-button type="primary">查询</el-button>
</header>
<main>
<el-row>
<el-col :span="8">
<h5>单位情况</h5>
<div class="row">
<div class="col col-24">
<label>单位名称</label>
<span>{{}}</span>
</div>
<div class="col col-24">
<label>所长</label>
<span>{{}}</span>
</div>
<div class="col col-24">
<label>副所长</label>
<span>{{}}</span>
</div>
</div>
<el-row>
<el-col :span="12">
<description-pair
label1="民警总人数"
label2="问题涉及民警数"
value1="132"
value2="21"
size="large"
/>
</el-col>
<el-col :span="12">
<description-pair
label1="协辅警人数"
label2="问题涉及协辅警数"
value1="132"
value2="21"
size="large"
/>
</el-col>
</el-row>
</el-col>
<el-col :span="8">
<h5>问题情况</h5>
<el-row>
<el-col :span="6" class="text-center">
<div class="text-primary" style="font-size: 34px">
51
</div>
<div>问题总数</div>
</el-col>
<el-col :span="18">
<el-row>
<el-col :span="12">
<description-pair
label1="110接处警量"
label2="问题数"
value1="132"
value2="21"
/>
</el-col>
<el-col :span="12">
<description-pair
label1="执法办案"
label2="问题数"
value1="132"
value2="21"
/>
</el-col>
</el-row>
</el-col>
</el-row>
</el-col>
<el-col :span="8">
<h5>风险指数</h5>
<div class="flex center">
<el-progress
type="dashboard"
:percentage="78"
:stroke-width="16"
:width="250"
color="#DC6231"
>
<div>
<span style="">78</span>
</div>
<div>分险指标值</div>
<div>中风险</div>
</el-progress>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<h5>问题来源占比</h5>
<v-charts
style="height: 320px"
:option="pieOptions"
autoresize
/>
</el-col>
<el-col :span="8">
<h5>业务类型占比</h5>
<v-charts
style="height: 320px"
:option="pieOptions"
autoresize
/>
</el-col>
<el-col :span="8">
<h5>风险问题构成</h5>
<v-charts
style="height: 320px"
:option="radarOption"
autoresize
/>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<h5>个人问题排名</h5>
<datav-chart-bar :data="barList" />
</el-col>
<el-col :span="8">
<h5>突出问题排名</h5>
<datav-chart-bar :data="barList" />
</el-col>
<el-col :span="8">
<h5>单位问题标签</h5>
<datav-chart-bar :data="barList" />
</el-col>
</el-row>
<h5>问题变化趋势</h5>
<v-charts style="height: 320px" :option="barOption" autoresize />
<div></div>
<h5>问题清单</h5>
<el-table>
<el-table-column label="发现时间" prop="" />
<el-table-column label="问题来源" prop="" />
<el-table-column label="业务类别" prop="" />
<el-table-column label="涉及单位" prop="" />
<el-table-column label="是否属实" prop="" width="180" />
<el-table-column
label="完善情况"
prop="departName"
width="120"
/>
<el-table-column
label="最后编辑人"
prop="fxzs"
width="120"
align="center"
/>
</el-table>
</main>
</el-dialog>
</template>
<script lang="ts" setup>
import vCharts from "vue-echarts";
import { listDepartNegative } from "@/api/sensitivePerception/profileDepart";
import { onMounted } from "vue";
const query = ref({
current: 1,
size: 10,
});
const list = ref<any[]>([]);
const total = ref(0);
function getList() {
}
onMounted(() => {
getList();
});
const show = ref(false);
const barList = [
{
label: "张三",
value: 67,
},
{
label: "李四",
value: 80,
},
{
label: "王五",
value: 40,
},
{
label: "王五",
value: 40,
},
{
label: "王五",
value: 10,
},
];
const pieOptions = computed(() => {
return {
series: [
{
type: "pie",
radius: ["40%", "70%"],
data: [
{ value: 311, name: "慢作为" },
{ value: 735, name: "意见建议" },
{ value: 580, name: "违法违纪违规" },
{ value: 484, name: "乱作为" },
{ value: 300, name: "其他" },
{ value: 300, name: "不作为" },
],
},
],
};
});
const radarOption = {
radar: {
// shape: 'circle',
indicator: [
{ name: "内部管理", max: 6500 },
{ name: "涉及监督", max: 6500 },
{ name: "记录作风", max: 30000 },
{ name: "警保卫工作", max: 38000 },
{ name: "执法办案", max: 52000 },
{ name: "专项工作", max: 25000 },
],
},
series: [
{
name: "Budget vs spending",
type: "radar",
data: [
{
value: [4200, 3000, 20000, 35000, 50000, 18000],
},
],
},
],
};
const barOption = {
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: "bar",
},
],
};
</script>
<style lang="scss" scoped>
</style>
Loading…
Cancel
Save