Browse Source

fit: 案件核查大屏。 fit: 警务人员增加角色 fit: 首页增加下钻到综合查询

main
wxc 1 year ago
parent
commit
07662633c6
  1. 50
      src/components/datav/chart-bar.vue
  2. 34
      src/views/Home.vue
  3. 255
      src/views/datav/CaseVerif.vue
  4. 26
      src/views/sensitivePerception/ModelClue.vue
  5. 2
      src/views/system/DictContent.vue
  6. 88
      src/views/system/Police.vue
  7. 19
      src/views/work/Query.vue

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

@ -4,8 +4,12 @@
<span class="bar-sub-title">{{ subTitle }}</span> <span class="bar-sub-title">{{ subTitle }}</span>
</div> </div>
<div> <div>
<div class="flex v-center bar-item between" v-for="item in data" :size="size"> <div
<span class="bar-item-name mr-10">{{ item.name }}</span> class="flex v-center bar-item between"
v-for="item in data"
:size="size"
>
<span class="bar-item-name mr-10">{{ item.label }}</span>
<div class="bar-item_content mr-16"> <div class="bar-item_content mr-16">
<div <div
class="bar-item_content-bar" class="bar-item_content-bar"
@ -15,8 +19,12 @@
}" }"
></div> ></div>
</div> </div>
<span class="mr-16">{{ item.value }}{{ item.unit }}</span> <span class="mr-16">{{ item.value }}</span>
<span class="bar-item_remark text-right" v-if="item.denominator" style="min-width: 40px"> <span
class="bar-item_remark text-right"
v-if="item.denominator"
style="min-width: 40px"
>
<span class="text-success">{{ item.numerator }}</span> <span class="text-success">{{ item.numerator }}</span>
<span>/</span> <span>/</span>
<span>{{ item.denominator }}</span> <span>{{ item.denominator }}</span>
@ -25,7 +33,9 @@
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps({ import { onMounted } from "vue";
const props = defineProps({
title: { title: {
type: String, type: String,
default: "", default: "",
@ -38,16 +48,34 @@ defineProps({
type: Array, type: Array,
default: [], default: [],
}, },
max: {
type: Number,
default: 100,
},
size: { size: {
type: String, type: String,
default: "", default: "",
}, },
unit: {
type: String,
default: "",
},
}); });
const max = ref(100);
watch(
() => props.data,
(arr) => {
getMax()
}
);
function getMax() {
if (props.unit !== "%") {
max.value = Math.max(...props.data.map((item) => item.value));
}
}
onMounted(() => {
getMax()
})
function getColor(val) { function getColor(val) {
if (val > 0.8) { if (val > 0.8) {
return "linear-gradient(270deg, #63e700 0%, #19674c 100%)"; return "linear-gradient(270deg, #63e700 0%, #19674c 100%)";
@ -70,7 +98,7 @@ function getColor(val) {
font-size: 17px; font-size: 17px;
height: 32px; height: 32px;
&[size="large"] { &[size="large"] {
height: 46px; height: 42px;
.bar-item_content { .bar-item_content {
.bar-item_content-bar { .bar-item_content-bar {
height: 13px; height: 13px;
@ -88,7 +116,7 @@ function getColor(val) {
height: 9px; height: 9px;
background: linear-gradient(270deg, #63e700 0%, #19674c 100%); background: linear-gradient(270deg, #63e700 0%, #19674c 100%);
box-shadow: 1px 0 0px 0px #020b5f; box-shadow: 1px 0 0px 0px #020b5f;
transition: width .3s; transition: width 0.3s;
} }
} }
.bar-item_remark { .bar-item_remark {

34
src/views/Home.vue

@ -7,6 +7,7 @@
:span="6" :span="6"
v-for="(item, index) in flowNumber" v-for="(item, index) in flowNumber"
:key="index" :key="index"
@click="goQuery(item)"
> >
<section class="flex column v-center overall-item pointer"> <section class="flex column v-center overall-item pointer">
<div> <div>
@ -26,7 +27,7 @@
<h2 class="text-bold">今日统计</h2> <h2 class="text-bold">今日统计</h2>
</div> </div>
<div class="flex wrap box"> <div class="flex wrap box">
<section class="flex column v-center daily-item pointer" v-for="item in todayNumber" :key="item.name"> <section class="flex column v-center daily-item pointer" v-for="item in todayNumber" :key="item.name" @click="goQuery2(item)">
<div class="number">{{ item.total }}</div> <div class="number">{{ item.total }}</div>
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
</section> </section>
@ -56,6 +57,37 @@ flowNumberAndTodayNumber().then(data => {
todayNumber.value = data.todayNumber; todayNumber.value = data.todayNumber;
}) })
const links = ['警务评议', '视频督察', '情指行', '执法办案'] const links = ['警务评议', '视频督察', '情指行', '执法办案']
const router = useRouter()
function goQuery(item) {
if (item.icon === 'sign') {
router.push('/query?processingStatus=signing')
}
if (item.icon === 'verify') {
router.push('/query?processingStatus=processing')
}
if (item.icon === 'delay') {
router.push('/query?processingStatus=signing')
}
if (item.icon === 'completedApprove') {
router.push('/query?processingStatus=approval')
}
}
function goQuery2(item) {
if (item.name === '今日问题') {
router.push('/query?crtTime=today')
}
if (item.name === '今日办结') {
}
if (item.name === '累计问题') {
router.push('/query')
}
if (item.name === '累计办结') {
router.push('/query?processingStatus=completed')
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.overall-item { .overall-item {

255
src/views/datav/CaseVerif.vue

@ -12,14 +12,13 @@
> >
<datav-tab-item label="分县市局" name="1"> <datav-tab-item label="分县市局" name="1">
<datav-chart-bar <datav-chart-bar
:data="data1" :data="fxsjBarList"
:max="11"
size="large" size="large"
/> />
</datav-tab-item> </datav-tab-item>
<datav-tab-item label="局属单位" name="2"> <datav-tab-item label="局属单位" name="2">
<datav-chart-bar <datav-chart-bar
:data="data1" :data="jsdwBarList"
:max="11" :max="11"
size="large" size="large"
/> />
@ -30,16 +29,24 @@
<datav-tabs v-model="activeTab"> <datav-tabs v-model="activeTab">
<datav-tab-item label="执法办案" name="1"> <datav-tab-item label="执法办案" name="1">
<v-charts <v-charts
style="height: 340px" style="height: 320px"
:option="option2" :option="zfbaPieOption"
autoresize autoresize
/> />
</datav-tab-item> </datav-tab-item>
<datav-tab-item label="服务管理" name="2"> <datav-tab-item label="服务管理" name="2">
<v-charts
style="height: 320px"
:option="fwglPieOption"
autoresize
/>
</datav-tab-item> </datav-tab-item>
<datav-tab-item label="警纪警规" name="3"> <datav-tab-item label="警纪警规" name="3">
<v-charts
style="height: 320px"
:option="jjjgPieOption"
autoresize
/>
</datav-tab-item> </datav-tab-item>
</datav-tabs> </datav-tabs>
</datav-card> </datav-card>
@ -80,13 +87,13 @@
/> />
</div> </div>
<v-charts <v-charts
style="height: 400px" style="height: 420px"
:option="option" :option="option"
autoresize autoresize
/> />
<datav-card title="查处问题趋势"> <datav-card title="查处问题趋势">
<v-charts <v-charts
style="height: 280px" style="height: 320px"
:option="option1" :option="option1"
autoresize autoresize
/> />
@ -96,11 +103,13 @@
<datav-card> <datav-card>
<datav-tabs v-model="activeTab"> <datav-tabs v-model="activeTab">
<datav-tab-item label="案件来源占比" name="1"> <datav-tab-item label="案件来源占比" name="1">
<v-charts <div class="mb-40">
style="height: 340px" <v-charts
:option="option3" style="height: 340px"
autoresize :option="ajlyPieOption"
/> autoresize
/>
</div>
</datav-tab-item> </datav-tab-item>
<datav-tab-item label="问责处理情况" name="2"> <datav-tab-item label="问责处理情况" name="2">
</datav-tab-item> </datav-tab-item>
@ -109,11 +118,13 @@
<datav-card> <datav-card>
<datav-tabs v-model="activeTab"> <datav-tabs v-model="activeTab">
<datav-tab-item label="停职处理情况" name="1"> <datav-tab-item label="停职处理情况" name="1">
<v-charts <div class="mb-40">
style="height: 340px" <v-charts
:option="option4" style="height: 340px"
autoresize :option="option4"
/> autoresize
/>
</div>
</datav-tab-item> </datav-tab-item>
<datav-tab-item label="禁闭处理情况" name="2"> <datav-tab-item label="禁闭处理情况" name="2">
</datav-tab-item> </datav-tab-item>
@ -129,10 +140,13 @@
import vCharts from "vue-echarts"; import vCharts from "vue-echarts";
import changshaMap from "@/assets/data/changsha.json"; import changshaMap from "@/assets/data/changsha.json";
import * as echarts from "echarts/core"; import * as echarts from "echarts/core";
import moment from 'moment' import moment from "moment";
import { getCaseVerifData } from '@/api/datav' import { getCaseVerifData } from "@/api/datav";
const time = ref([moment().startOf('year').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')]) const time = ref([
moment().startOf("year").format("YYYY-MM-DD"),
moment().format("YYYY-MM-DD"),
]);
const overview = ref({ const overview = ref({
total: 0, total: 0,
@ -140,19 +154,95 @@ const overview = ref({
investigateAndPunish: 0, investigateAndPunish: 0,
accountablePeopleNumber: 0, accountablePeopleNumber: 0,
accountableDepartNumber: 0, accountableDepartNumber: 0,
confirmedRate: 0 confirmedRate: 0,
}) });
const fxsjBarList = ref([]);
const jsdwBarList = ref([]);
const zfbaPieList = ref([]);
const fwglPieList = ref([]);
const jjjgPieList = ref([]);
const ajlyPieList = ref([]);
function getData() { function getData() {
getCaseVerifData(time.value).then(data => { getCaseVerifData(time.value).then((data) => {
overview.value = data.overview overview.value = data.overview;
}) fxsjBarList.value = data.fxsjBarList;
jsdwBarList.value = data.jsdwBarList;
zfbaPieList.value = data.zfbaPieList;
fwglPieList.value = data.fwglPieList;
jjjgPieList.value = data.jjjgPieList;
ajlyPieList.value = data.ajlyPieList;
});
} }
onMounted(() => { watch(time, () => {
getData() getData();
}) })
onMounted(() => {
getData();
});
const zfbaPieOption = computed(() => {
return {
series: [
{
type: "pie",
radius: ["40%", "70%"],
label: {
color: "#fff",
},
data: zfbaPieList.value,
},
],
};
});
const fwglPieOption = computed(() => {
return {
series: [
{
type: "pie",
radius: ["40%", "70%"],
label: {
color: "#fff",
},
data: fwglPieList.value,
},
],
};
});
const jjjgPieOption = computed(() => {
return {
series: [
{
type: "pie",
radius: ["40%", "70%"],
label: {
color: "#fff",
},
data: jjjgPieList.value,
},
],
};
});
const ajlyPieOption = computed(() => {
return {
series: [
{
type: "pie",
radius: ["40%", "70%"],
label: {
color: "#fff",
},
data: ajlyPieList.value,
},
],
};
});
echarts.registerMap("changsha", changshaMap); echarts.registerMap("changsha", changshaMap);
const option = { const option = {
@ -160,7 +250,6 @@ const option = {
// registerMap'' // registerMap''
map: "changsha", map: "changsha",
}, },
visualMap: { visualMap: {
type: "piecewise", type: "piecewise",
bottom: 10, bottom: 10,
@ -192,9 +281,7 @@ const option = {
color: "white", color: "white",
}, },
itemStyle: { itemStyle: {
normal: { areaColor: "#02215E", //
areaColor: "#02215E", //
},
}, },
}, },
], ],
@ -261,108 +348,6 @@ const option1 = ref({
], ],
}); });
const data1 = [
{
name: "开福分局",
value: 11,
},
{
name: "芙蓉分局",
value: 9,
},
{
name: "岳麓分局",
value: 7,
},
{
name: "雨花分局",
value: 4,
},
{
name: "望城分局",
value: 3,
},
{
name: "浏阳市局",
value: 3,
},
{
name: "长沙县局",
value: 1,
},
];
const data2 = [
{
name: "开福分局",
value: 9700,
},
{
name: "芙蓉分局",
value: 9021,
},
{
name: "岳麓分局",
value: 8512,
},
{
name: "雨花分局",
value: 8021,
},
{
name: "望城分局",
value: 7111,
},
{
name: "浏阳市局",
value: 6622,
},
{
name: "长沙县局",
value: 6221,
},
];
const option2 = {
series: [
{
type: "pie",
radius: ["40%", "70%"],
label: {
color: "#fff",
},
data: [
{ value: 311, name: "违规办案" },
{ value: 735, name: "不作为" },
{ value: 580, name: "乱作为" },
{ value: 484, name: "慢作为" },
{ value: 300, name: "暴力执法" },
{ value: 300, name: "执法不规范" },
],
},
],
};
const option3 = {
series: [
{
type: "pie",
radius: ["40%", "70%"],
label: {
color: "#fff",
},
data: [
{ value: 311, name: "自办" },
{ value: 735, name: "13489" },
{ value: 580, name: "队领导交办" },
{ value: 484, name: "局领导交办" },
{ value: 300, name: "公安部领导交办" },
{ value: 300, name: "市局主要领导交办" },
],
},
],
};
const option4 = { const option4 = {
series: [ series: [
{ {

26
src/views/sensitivePerception/ModelClue.vue

@ -79,7 +79,7 @@
width="200" width="200"
> >
<template #default="{ row }"> <template #default="{ row }">
<span>{{ row.involveParentDepartName }}</span> <span>{{ row.involveDepartName }}</span> <span>{{ activeModelClue.involveParentDepartName }}</span><span>{{ activeModelClue.involveDepartName ? '/' + activeModelClue.involveDepartName : '' }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -114,6 +114,13 @@
@click="handleShowDetail(row)" @click="handleShowDetail(row)"
>查看详情</el-button >查看详情</el-button
> >
<el-button
v-if="row.negativeId"
type="primary"
link
@click="handleAction(row)"
>处理详情</el-button
>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -150,7 +157,7 @@
<div class="col col-6"> <div class="col col-6">
<label>涉及单位</label> <label>涉及单位</label>
<span> <span>
<span>{{ activeModelClue.involveParentDepartName }}</span> <span>{{ activeModelClue.involveDepartName }}</span> <span>{{ activeModelClue.involveParentDepartName }}</span><span>{{ activeModelClue.involveDepartName ? '/' + activeModelClue.involveDepartName : '' }}</span>
</span> </span>
</div> </div>
<div class="col col-6"> <div class="col col-6">
@ -181,6 +188,12 @@
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
<negative-dialog
v-model="negativeShow"
:id="activeNegativeId"
@close="negativeShow = false"
/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { listModelClue } from "@/api/sensitivePerception/modelClue"; import { listModelClue } from "@/api/sensitivePerception/modelClue";
@ -232,6 +245,15 @@ function handleShowDetail(row) {
activeModelClue.value = row; activeModelClue.value = row;
show.value = true; show.value = true;
} }
const activeNegativeId = ref('')
const negativeShow = ref(false)
function handleAction(row) {
negativeShow.value = true;
activeNegativeId.value = row.negativeId;
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
</style> </style>

2
src/views/system/DictContent.vue

@ -14,9 +14,7 @@
<div class="table-container"> <div class="table-container">
<el-table :data="dictContents" row-key="id"> <el-table :data="dictContents" row-key="id">
<el-table-column label="类型名称" prop="name" show-overflow-tooltip="" /> <el-table-column label="类型名称" prop="name" show-overflow-tooltip="" />
<el-table-column label="类型编码" prop="code" width="200" />
<el-table-column label="序号" prop="sort" width="200" /> <el-table-column label="序号" prop="sort" width="200" />
<el-table-column label="序号" prop="level" width="200" />
<el-table-column label="最后更新时间" prop="updTime" /> <el-table-column label="最后更新时间" prop="updTime" />
<el-table-column label="操作"> <el-table-column label="操作">
<template #default="{ row }"> <template #default="{ row }">

88
src/views/system/Police.vue

@ -59,6 +59,22 @@
</div> </div>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="权限角色">
<el-select
v-model="query.roleId"
placeholder="请选择角色"
clearable
>
<el-option
v-for="item in roles"
:key="item.roleId"
:value="item.roleId"
:label="item.roleName"
/>
</el-select>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="mb-25 flex between"> <div class="mb-25 flex between">
@ -99,6 +115,16 @@
) )
}}</span> }}</span>
</div> </div>
<div class="col col-6">
<label>备注</label>
<span>{{ row.job }}</span>
</div>
</div>
<div class="row mt-10">
<div class="col col-6">
<label>电话</label>
<span>{{ row.mobile }}</span>
</div>
<div class="col col-6"> <div class="col col-6">
<label>入职时间</label> <label>入职时间</label>
<span>{{ row.employmentDate }}</span> <span>{{ row.employmentDate }}</span>
@ -136,7 +162,9 @@
<el-table-column label="所属机构" show-overflow-tooltip> <el-table-column label="所属机构" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<div class="flex gap-4"> <div class="flex gap-4">
<span v-if="row.parentDepartShortName">{{ row.parentDepartShortName }}/</span><span>{{ row.departShortName }}</span> <span v-if="row.parentDepartShortName"
>{{ row.parentDepartShortName }}/</span
><span>{{ row.departShortName }}</span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -147,21 +175,35 @@
}}</span> }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="职位" prop="position" width="120" align="center" > <el-table-column label="职位" width="120" align="center">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row.position"> <span v-if="row.position">
<span v-if="row.level === 0">局领导{{ row.position }}</span> <span v-if="row.level === 0"
<span v-if="row.level === 2">二级机构{{ row.position }}</span> >局领导{{ row.position }}</span
<span v-if="row.level === 3">三机机构{{ row.position }}</span> >
<span v-if="row.level === 4">四机机构{{ row.position }}</span> <span v-if="row.level === 2"
>二级机构{{ row.position }}</span
>
<span v-if="row.level === 3"
>三机机构{{ row.position }}</span
>
<span v-if="row.level === 4"
>四机机构{{ row.position }}</span
>
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="备注" prop="job" width="140" show-overflow-tooltip />
<el-table-column label="身份证" prop="idCode" width="200" /> <el-table-column label="身份证" prop="idCode" width="200" />
<el-table-column label="电话" prop="mobile" width="120" show-overflow-tooltip /> <el-table-column label="角色" show-overflow-tooltip>
<template #default="{ row }">
<div class="flex gap" v-if="row.role">
<el-tag v-for="item in row.role.split(',')">{{
item
}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="220"> <el-table-column label="操作" width="220">
<template #default="{ row }"> <template #default="{ row }">
<el-button <el-button
@ -229,7 +271,6 @@
filterable filterable
v-model="authForm.sources" v-model="authForm.sources"
multiple multiple
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -304,7 +345,7 @@
}" }"
> >
<div style="width: 280px"> <div style="width: 280px">
<depart-tree-select v-model="form.orgId" :showRoot="true" /> <depart-tree-select v-model="form.orgId" :showRoot="true" />
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="人员属性"> <el-form-item label="人员属性">
@ -317,7 +358,11 @@
> >
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="职位" prop="position" v-if="form.personType === PersonType.POLICE"> <el-form-item
label="职位"
prop="position"
v-if="form.personType === PersonType.POLICE"
>
<el-select <el-select
v-model="form.position" v-model="form.position"
clearable clearable
@ -365,7 +410,7 @@
> >
</div> </div>
</el-form-item> </el-form-item>
<!-- <el-form-item label="婚姻状况"> <!-- <el-form-item label="婚姻状况">
<el-radio-group v-model="form.maritalStatus"> <el-radio-group v-model="form.maritalStatus">
<el-radio <el-radio
@ -409,7 +454,8 @@ import {
delPolice, delPolice,
updatePoliceAuths, updatePoliceAuths,
} from "@/api/system/police"; } from "@/api/system/police";
import { PersonType } from '@/enums/dictEnums' import { listRole } from "@/api/system/role";
import { PersonType } from "@/enums/dictEnums";
import useCatchStore from "@/stores/modules/catch"; import useCatchStore from "@/stores/modules/catch";
import feedback from "@/utils/feedback"; import feedback from "@/utils/feedback";
import { getDictLable } from "@/utils/util"; import { getDictLable } from "@/utils/util";
@ -443,8 +489,12 @@ function getList() {
}); });
} }
const roles = ref([]);
onMounted(() => { onMounted(() => {
getList(); getList();
listRole().then((data) => {
roles.value = data;
});
}); });
function reset() { function reset() {
@ -529,10 +579,10 @@ function getWorkYear(employmentDate) {
} }
async function handleDel(row) { async function handleDel(row) {
await feedback.confirm(`确定要删除 ${row.name}`) await feedback.confirm(`确定要删除 ${row.name}`);
await delPolice(row.id) await delPolice(row.id);
feedback.msgSuccess('操作成功') feedback.msgSuccess("操作成功");
getList() getList();
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

19
src/views/work/Query.vue

@ -446,11 +446,11 @@
<negative-dialog <negative-dialog
v-model="show" v-model="show"
:id="activeNegativeId" :id="activeNegativeId"
@change="getList"
@close="show = false" @close="show = false"
/> />
</template> </template>
<script setup> <script setup>
import moment from "moment";
import { ElLoading } from "element-plus"; import { ElLoading } from "element-plus";
import { listNegative, negativeExport, delNegative } from "@/api/work/negative"; import { listNegative, negativeExport, delNegative } from "@/api/work/negative";
import { getDictLable, formatTimeText, getInvolveProblem } from "@/utils/util"; import { getDictLable, formatTimeText, getInvolveProblem } from "@/utils/util";
@ -497,8 +497,25 @@ function reset() {
responderKey: "name", responderKey: "name",
}; };
getList(); getList();
//
router.push('/query')
} }
const route = useRoute()
watch(() => route.query, () => {
if (route.query.processingStatus) {
query.value.processingStatus = [route.query.processingStatus]
} else {
query.value.processingStatus = []
}
if (route.query.crtTime === 'today') {
query.value.crtTime = [moment().startOf("day").format("YYYY-MM-DD HH:mm:ss"), moment().endOf("day").format("YYYY-MM-DD HH:mm:ss")]
} else {
query.value.crtTime = []
}
getList()
})
onMounted(() => { onMounted(() => {
getList(); getList();
}); });

Loading…
Cancel
Save