45 changed files with 24953 additions and 23217 deletions
@ -0,0 +1,15 @@ |
|||||||
|
import request from "@/api/request"; |
||||||
|
|
||||||
|
export function addInspection(body) { |
||||||
|
return request.post({ |
||||||
|
url: '/task/inspection', |
||||||
|
body |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
export function listInspection(query) { |
||||||
|
return request.get({ |
||||||
|
url: '/task/inspection', |
||||||
|
query |
||||||
|
}); |
||||||
|
} |
||||||
@ -0,0 +1,22 @@ |
|||||||
|
import request from "@/api/request"; |
||||||
|
|
||||||
|
export function getPersonNumber(query) { |
||||||
|
return request.get({ |
||||||
|
url: '/task/testingAlcohol/getPersonNumber', |
||||||
|
query |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
export function addTestingAlcohol(body) { |
||||||
|
return request.post({ |
||||||
|
url: '/task/testingAlcohol', |
||||||
|
body |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
export function listTestingAlcohol(query) { |
||||||
|
return request.get({ |
||||||
|
url: '/task/testingAlcohol', |
||||||
|
query |
||||||
|
}); |
||||||
|
} |
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -1,195 +1,192 @@ |
|||||||
<template> |
<template> |
||||||
<div class="flex between v-center mb-10"> |
<div class="flex between v-center mb-10"> |
||||||
<span class="bar-title">{{ title }}</span> |
<span class="bar-title">{{ title }}</span> |
||||||
<span class="bar-sub-title">{{ subTitle }}</span> |
<span class="bar-sub-title">{{ subTitle }}</span> |
||||||
</div> |
</div> |
||||||
<div> |
<div> |
||||||
<div |
<div |
||||||
class="flex v-center bar-item wrap between " |
class="flex v-center bar-item wrap between" |
||||||
v-for="item in data" |
v-for="item in data" |
||||||
:size="size" |
:size="size" |
||||||
:style="{ '--label-width': `${labelWidth}px` }" |
:style="{ '--label-width': `${labelWidth}px` }" |
||||||
:position="labelPosition" |
:position="labelPosition" |
||||||
style="height: 40px" |
style="height: 40px" |
||||||
> |
> |
||||||
<span style="margin-left: 18px"> |
<span style="margin-left: 18px"> |
||||||
{{ item.sort }} |
{{ item.sort }} |
||||||
</span> |
</span> |
||||||
<div class="bar-item_content mr-8 " :long="!item.denominator"> |
<div class="bar-item_content mr-8" :long="!item.denominator"> |
||||||
<span>{{ item.label }}</span> |
<span :title="item.label">{{ item.label }}</span> |
||||||
<div |
<div |
||||||
class="bar-item_content-bar" |
class="bar-item_content-bar" |
||||||
:style="{ |
:style="{ |
||||||
width: `${(item.value / max) * 100}%`, |
width: `${(item.value / max) * 100}%`, |
||||||
background: getColor((item.value / max) * 100), |
background: getColor((item.value / max) * 100), |
||||||
}" |
}" |
||||||
></div> |
></div> |
||||||
</div> |
</div> |
||||||
<span>{{ item.value }}</span> |
<span>{{ item.value }}</span> |
||||||
<span |
<span |
||||||
class="bar-item_remark text-right ml-8" |
class="bar-item_remark text-right ml-8" |
||||||
v-if="item.denominator" |
v-if="item.denominator" |
||||||
style="min-width: 40px" |
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> |
||||||
</span> |
</span> |
||||||
|
</div> |
||||||
</div> |
</div> |
||||||
</div> |
|
||||||
</template> |
</template> |
||||||
<script setup> |
<script setup> |
||||||
import {onMounted} from "vue"; |
import { onMounted } from "vue"; |
||||||
|
|
||||||
const props = defineProps({ |
const props = defineProps({ |
||||||
title: { |
title: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
subTitle: { |
subTitle: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
data: { |
data: { |
||||||
type: Array, |
type: Array, |
||||||
default: [], |
default: [], |
||||||
}, |
}, |
||||||
size: { |
size: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
unit: { |
unit: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
color: { |
color: { |
||||||
type: Object, |
type: Object, |
||||||
default: "linear-gradient(270deg, #63e700 0%, #19674c 100%)", |
default: "linear-gradient(270deg, #63e700 0%, #19674c 100%)", |
||||||
}, |
}, |
||||||
labelWidth: { |
labelWidth: { |
||||||
type: Number, |
type: Number, |
||||||
default: 60, |
default: 60, |
||||||
}, |
}, |
||||||
labelPosition: { |
labelPosition: { |
||||||
type: String, |
type: String, |
||||||
default: "left", |
default: "left", |
||||||
}, |
}, |
||||||
}); |
}); |
||||||
|
|
||||||
const max = ref(100); |
const max = ref(100); |
||||||
watch( |
watch( |
||||||
() => props.data, |
() => props.data, |
||||||
() => { |
() => { |
||||||
getMax(); |
getMax(); |
||||||
} |
} |
||||||
); |
); |
||||||
|
|
||||||
function getMax() { |
function getMax() { |
||||||
if (props.unit !== "%") { |
if (props.unit !== "%") { |
||||||
max.value = Math.max(...props.data.map((item) => item.value)); |
max.value = Math.max(...props.data.map((item) => item.value)); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
onMounted ( () => { |
onMounted(() => { |
||||||
getMax(); |
getMax(); |
||||||
|
|
||||||
}); |
}); |
||||||
|
|
||||||
function getColor(val) { |
function getColor(val) { |
||||||
if (props.color instanceof String) { |
if (props.color instanceof String) { |
||||||
return props.color; |
return props.color; |
||||||
} |
|
||||||
if (props.color instanceof Array) { |
|
||||||
const colors = [...props.color]; |
|
||||||
colors.sort((a, b) => b.percentage - a.percentage); |
|
||||||
for (let i = 0; i < colors.length; i++) { |
|
||||||
if (val > colors[0].percentage) { |
|
||||||
return colors[0].color; |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
if (props.color instanceof Array) { |
||||||
return "linear-gradient(270deg, #63e700 0%, #19674c 100%)"; |
const colors = [...props.color]; |
||||||
// if (val >= 0.7) { |
colors.sort((a, b) => b.percentage - a.percentage); |
||||||
// return "linear-gradient( 270deg, #FFB90E 0%, #71501D 100%)"; |
for (let i = 0; i < colors.length; i++) { |
||||||
// } |
if (val > colors[0].percentage) { |
||||||
// return "linear-gradient( 270deg, #FB002D 0%, #822232 100%)"; |
return colors[0].color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
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> |
</script> |
||||||
<style lang="scss" scoped> |
<style lang="scss" scoped> |
||||||
.bar-title { |
.bar-title { |
||||||
font-size: 19px; |
font-size: 19px; |
||||||
} |
} |
||||||
|
|
||||||
.bar-sub-title { |
.bar-sub-title { |
||||||
color: #597ae9; |
color: #597ae9; |
||||||
font-size: 14px; |
font-size: 14px; |
||||||
} |
} |
||||||
|
|
||||||
.bar-item { |
.bar-item { |
||||||
font-size: 17px; |
font-size: 17px; |
||||||
|
&[size="large"] { |
||||||
&[size="large"] { |
.bar-item_content { |
||||||
.bar-item_content { |
.bar-item_content-bar { |
||||||
.bar-item_content-bar { |
height: 13px; |
||||||
height: 13px; |
} |
||||||
|
} |
||||||
} |
|
||||||
} |
} |
||||||
} |
|
||||||
|
|
||||||
&[size="small"] { |
&[size="small"] { |
||||||
font-size: 12px; |
font-size: 12px; |
||||||
} |
} |
||||||
|
|
||||||
.bar-item-label { |
|
||||||
text-align: right; |
|
||||||
width: var(--label-width); |
|
||||||
overflow: hidden; |
|
||||||
white-space: nowrap; |
|
||||||
text-overflow: ellipsis; |
|
||||||
} |
|
||||||
|
|
||||||
&[position="left"] { |
|
||||||
height: 32px; |
|
||||||
line-height: 32px; |
|
||||||
} |
|
||||||
|
|
||||||
&[position="top"] { |
|
||||||
margin-bottom: 4px; |
|
||||||
|
|
||||||
.bar-item-label { |
.bar-item-label { |
||||||
width: 100%; |
text-align: right; |
||||||
text-align: left; |
width: var(--label-width); |
||||||
|
overflow: hidden; |
||||||
|
white-space: nowrap; |
||||||
|
text-overflow: ellipsis; |
||||||
} |
} |
||||||
|
|
||||||
.bar-item_content { |
&[position="left"] { |
||||||
width: calc(100% - 80px); |
height: 32px; |
||||||
|
line-height: 32px; |
||||||
|
white-space: nowrap; |
||||||
|
width: 100%; |
||||||
} |
} |
||||||
} |
|
||||||
|
|
||||||
.bar-item_content { |
&[position="top"] { |
||||||
width: calc(100% - var(--label-width) - 16px - 30px); |
margin-bottom: 4px; |
||||||
|
.bar-item-label { |
||||||
|
width: 100%; |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
|
||||||
&[long=false] { |
.bar-item_content { |
||||||
width: calc(100% - var(--label-width) - 36px - 58px); |
width: calc(100% - 80px); |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
.bar-item_content-bar { |
.bar-item_content { |
||||||
width: 0; |
width: calc(100% - var(--label-width) - 16px - 30px); |
||||||
height: 9px; |
overflow: hidden; |
||||||
background: linear-gradient(270deg, #63e700 0%, #19674c 100%); |
text-overflow: ellipsis; |
||||||
transition: width 0.3s; |
&[long="false"] { |
||||||
|
width: calc(100% - var(--label-width) - 36px - 58px); |
||||||
|
} |
||||||
|
|
||||||
|
.bar-item_content-bar { |
||||||
|
width: 0; |
||||||
|
height: 9px; |
||||||
|
background: linear-gradient(270deg, #63e700 0%, #19674c 100%); |
||||||
|
transition: width 0.3s; |
||||||
|
} |
||||||
} |
} |
||||||
} |
|
||||||
|
|
||||||
.bar-item_remark { |
.bar-item_remark { |
||||||
font-size: 14px; |
font-size: 14px; |
||||||
|
|
||||||
.text-success { |
.text-success { |
||||||
color: #09c700; |
color: #09c700; |
||||||
|
} |
||||||
} |
} |
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
|
|
||||||
</style> |
</style> |
||||||
@ -0,0 +1,216 @@ |
|||||||
|
<template> |
||||||
|
<div class="flex gap"> |
||||||
|
<el-tag type="info" effect="plain" closable v-for="item in modelValue" :key="item">{{ item.name }}</el-tag> |
||||||
|
<el-button size="small" type="primary" plain @click="show = true"> |
||||||
|
<template #icon> |
||||||
|
<icon name="el-icon-Plus" /> |
||||||
|
</template> |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
|
<el-dialog title="选择警员" v-model="show" width="60vw" top="5vh"> |
||||||
|
<div style="min-height: 70vh"> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="6"> |
||||||
|
<el-scrollbar max-height="70vh"> |
||||||
|
<el-tree |
||||||
|
:data="treeData" |
||||||
|
:props="{ label: 'shortName', value: 'id' }" |
||||||
|
:default-expanded-keys="['12630']" |
||||||
|
@node-click="handleSelectDepart" |
||||||
|
/> |
||||||
|
</el-scrollbar> |
||||||
|
</el-col> |
||||||
|
<el-col :span="18"> |
||||||
|
<header class="flex between mb-20"> |
||||||
|
<div class="flex gap"> |
||||||
|
<el-input |
||||||
|
placeholder="警员姓名" |
||||||
|
v-model="query.name" |
||||||
|
clearable |
||||||
|
style="width: 220px" |
||||||
|
/> |
||||||
|
<el-input |
||||||
|
placeholder="请输入" |
||||||
|
v-model="query.empNo" |
||||||
|
clearable |
||||||
|
style="width: 220px" |
||||||
|
/> |
||||||
|
<el-input |
||||||
|
placeholder="身份证号码" |
||||||
|
v-model="query.idCode" |
||||||
|
clearable |
||||||
|
style="width: 220px" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<el-button type="primary">查询</el-button> |
||||||
|
</header> |
||||||
|
<div class="table-container"> |
||||||
|
<el-table |
||||||
|
:data="polices" |
||||||
|
row-key="id" |
||||||
|
max-height="890px" |
||||||
|
@selection-change="selectionChange" |
||||||
|
> |
||||||
|
<el-table-column type="selection" width="55" /> |
||||||
|
<el-table-column |
||||||
|
label="姓名" |
||||||
|
prop="name" |
||||||
|
width="90" |
||||||
|
/> |
||||||
|
<el-table-column |
||||||
|
label="警号" |
||||||
|
prop="empNo" |
||||||
|
width="100" |
||||||
|
show-overflow-tooltip |
||||||
|
/> |
||||||
|
<el-table-column |
||||||
|
label="所属机构" |
||||||
|
show-overflow-tooltip |
||||||
|
> |
||||||
|
<template #default="{ row }"> |
||||||
|
<div class="flex gap-4"> |
||||||
|
<span v-if="row.parentDepartShortName" |
||||||
|
>{{ |
||||||
|
row.parentDepartShortName |
||||||
|
}}/</span |
||||||
|
><span>{{ row.departShortName }}</span> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
label="人员属性" |
||||||
|
width="120" |
||||||
|
align="center" |
||||||
|
> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span>{{ |
||||||
|
getDictLable( |
||||||
|
dict.personType, |
||||||
|
row.personType |
||||||
|
) |
||||||
|
}}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
label="职位" |
||||||
|
width="120" |
||||||
|
align="center" |
||||||
|
> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span v-if="row.position"> |
||||||
|
<span v-if="row.level === 0" |
||||||
|
>局领导{{ 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> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
label="身份证" |
||||||
|
prop="idCode" |
||||||
|
width="200" |
||||||
|
/> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
<div class="flex end mt-8"> |
||||||
|
<el-pagination |
||||||
|
@size-change="getList" |
||||||
|
@current-change="getList" |
||||||
|
:page-sizes="[10, 20]" |
||||||
|
v-model:page-size="query.size" |
||||||
|
v-model:current-page="query.current" |
||||||
|
layout="total, sizes, prev, pager, next" |
||||||
|
:total="total" |
||||||
|
> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
<div class="flex gap mt-10 wrap v-center"> |
||||||
|
<span>已选警员:</span> |
||||||
|
<el-tag |
||||||
|
v-for="item in checkPolices" |
||||||
|
:key="item" |
||||||
|
closable |
||||||
|
>{{ item.name }}</el-tag |
||||||
|
> |
||||||
|
</div> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</div> |
||||||
|
<footer class="flex end"> |
||||||
|
<el-button @click="show = false">取消</el-button> |
||||||
|
<el-button type="primary" @click="submit">确定</el-button> |
||||||
|
</footer> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
<script setup> |
||||||
|
import { departTreeList } from "@/api/system/depart"; |
||||||
|
import { listPolice } from "@/api/system/police"; |
||||||
|
import useCatchStore from "@/stores/modules/catch"; |
||||||
|
import { getDictLable } from "@/utils/util"; |
||||||
|
|
||||||
|
const catchSotre = useCatchStore(); |
||||||
|
const dict = catchSotre.getDicts(["personType"]); |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
modelValue: { |
||||||
|
type: Array, |
||||||
|
default: [] |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue']) |
||||||
|
|
||||||
|
const show = ref(false); |
||||||
|
const query = ref({ |
||||||
|
departBranch: true, |
||||||
|
}); |
||||||
|
const total = ref(0); |
||||||
|
|
||||||
|
const treeData = catchSotre.getDepartsAll(); |
||||||
|
const polices = ref([]); |
||||||
|
function getList() { |
||||||
|
listPolice(query.value).then((data) => { |
||||||
|
polices.value = data.records; |
||||||
|
total.value = data.total; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
const checkPolices = ref([]); |
||||||
|
|
||||||
|
function selectionChange(selectionRows) { |
||||||
|
checkPolices.value = selectionRows.map(item => { |
||||||
|
return { |
||||||
|
name: item.name, |
||||||
|
empNo: item.empNo, |
||||||
|
idCode: item.idCode |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function handleSelectDepart(node) { |
||||||
|
query.value.departId = node.id; |
||||||
|
getList(); |
||||||
|
} |
||||||
|
|
||||||
|
function submit() { |
||||||
|
emit('update:modelValue', checkPolices.value) |
||||||
|
show.value = false |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
getList(); |
||||||
|
}); |
||||||
|
</script> |
||||||
|
<style lang="scss"> |
||||||
|
.el-tree-node.is-current > .el-tree-node__content { |
||||||
|
background-color: #e8e9f3; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,278 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<header class="mb-20"> |
||||||
|
<el-form :label-width="114"> |
||||||
|
<el-row> |
||||||
|
<el-col :span="6"> |
||||||
|
<el-form-item label="督察单位"> |
||||||
|
<depart-tree-select v-model="query.departId" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="6"> |
||||||
|
<el-form-item label="任务名称"> |
||||||
|
<el-input |
||||||
|
placeholder="请输入任务名称" |
||||||
|
v-model="query.nickName" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="6"> |
||||||
|
<el-form-item label="督察类型"> |
||||||
|
<el-select v-model="form.supervisionType" clearable> |
||||||
|
<el-option |
||||||
|
v-for="item in dict.supervisionType" |
||||||
|
:key="item.id" |
||||||
|
:label="item.dictLabel" |
||||||
|
:value="item.dictValue" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
<div class="flex between"> |
||||||
|
<el-button type="primary" @click="handleShowAdd"> |
||||||
|
<template #icon> |
||||||
|
<icon name="el-icon-Plus" /> |
||||||
|
</template> |
||||||
|
发布任务</el-button |
||||||
|
> |
||||||
|
<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="taskName" /> |
||||||
|
<el-table-column |
||||||
|
label="督察单位" |
||||||
|
prop="supDepartName" |
||||||
|
width="120" |
||||||
|
/> |
||||||
|
<el-table-column |
||||||
|
label="参与人员" |
||||||
|
prop="testingPerson" |
||||||
|
show-overflow-tooltip |
||||||
|
/> |
||||||
|
<el-table-column |
||||||
|
label="任务类型" |
||||||
|
prop="supervisionType" |
||||||
|
width="100" |
||||||
|
align="center" |
||||||
|
/> |
||||||
|
<el-table-column label="任务内容" prop="taskContent" /> |
||||||
|
<el-table-column label="督察时间" prop="updateTime" width="280"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span>{{ row.beginTime }}</span> |
||||||
|
<span>-</span> |
||||||
|
<span>{{ row.endTime }}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="任务状态"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span v-if="row.taskStatus === 'todo'">执行中</span> |
||||||
|
<span v-if="row.taskStatus === 'done'">已完成</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="被督察单位数" prop="" /> |
||||||
|
<el-table-column label="发现问题数" prop="" /> |
||||||
|
<el-table-column label="操作" width="200"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-button type="primary" link>查看详情</el-button> |
||||||
|
<el-button type="primary" link>问题清单</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
<div class="flex end mt-8"> |
||||||
|
<el-pagination |
||||||
|
@size-change="getList" |
||||||
|
@current-change="getList" |
||||||
|
:page-sizes="[10, 20, 50]" |
||||||
|
v-model:page-size="query.size" |
||||||
|
v-model:current-page="query.current" |
||||||
|
layout="total, sizes, prev, pager, next" |
||||||
|
:total="total" |
||||||
|
> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog |
||||||
|
title="发布任务" |
||||||
|
v-model="show" |
||||||
|
width="1076px" |
||||||
|
top="5vh" |
||||||
|
style="margin-bottom: 0" |
||||||
|
> |
||||||
|
<el-scrollbar max-height="66vh"> |
||||||
|
<el-form |
||||||
|
:label-width="150" |
||||||
|
ref="formRef" |
||||||
|
:model="form" |
||||||
|
style="min-height: 66vh" |
||||||
|
> |
||||||
|
<el-form-item |
||||||
|
label="任务名称" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请输入任务名称', |
||||||
|
trigger: ['blur'], |
||||||
|
}" |
||||||
|
prop="taskName" |
||||||
|
> |
||||||
|
<el-input |
||||||
|
v-model="form.taskName" |
||||||
|
placeholder="请输入任务名称" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="督察单位" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
prop="supDepartId" |
||||||
|
> |
||||||
|
<div style="width: 300px"> |
||||||
|
<depart-tree-select v-model="form.supDepartId" /> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="督察人员" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
prop="persons" |
||||||
|
> |
||||||
|
<police-picker v-model="form.persons" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="督察类型" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
prop="supervisionType" |
||||||
|
> |
||||||
|
<el-select |
||||||
|
v-model="form.supervisionType" |
||||||
|
clearable |
||||||
|
style="width: 300px" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="item in dict.supervisionType" |
||||||
|
:key="item.id" |
||||||
|
:label="item.dictLabel" |
||||||
|
:value="item.dictValue" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="督察时间" |
||||||
|
prop="times" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
> |
||||||
|
<div style="width: 800px"> |
||||||
|
<el-date-picker |
||||||
|
v-model="form.times" |
||||||
|
type="datetimerange" |
||||||
|
range-separator="-" |
||||||
|
start-placeholder="开始时间" |
||||||
|
end-placeholder="结束时间" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="任务内容" |
||||||
|
prop="times" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
> |
||||||
|
<el-input |
||||||
|
type="textarea" |
||||||
|
v-model="form.taskContent" |
||||||
|
:autosize="{ minRows: 6 }" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</el-scrollbar> |
||||||
|
<footer class="flex end mt-20"> |
||||||
|
<el-button type="primary" @click="submit" size="large" |
||||||
|
>发布</el-button |
||||||
|
> |
||||||
|
</footer> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
<script setup> |
||||||
|
import { |
||||||
|
listInspection, |
||||||
|
addInspection, |
||||||
|
} from "@/api/mobileSupervision/inspection"; |
||||||
|
import feedback from "@/utils/feedback"; |
||||||
|
import useCatchStore from "@/stores/modules/catch"; |
||||||
|
|
||||||
|
const catchStore = useCatchStore(); |
||||||
|
const dict = catchStore.getDicts(["supervisionType"]); |
||||||
|
|
||||||
|
const list = ref([]); |
||||||
|
const query = ref({ |
||||||
|
current: 1, |
||||||
|
size: 10, |
||||||
|
}); |
||||||
|
const total = ref(0); |
||||||
|
function getList() { |
||||||
|
listInspection(query.value).then((data) => { |
||||||
|
list.value = data.records; |
||||||
|
total.value = data.total; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function reset() { |
||||||
|
query.value = { |
||||||
|
current: 1, |
||||||
|
size: 10, |
||||||
|
}; |
||||||
|
getList(); |
||||||
|
} |
||||||
|
|
||||||
|
getList(); |
||||||
|
|
||||||
|
const show = ref(false); |
||||||
|
|
||||||
|
const form = ref({}); |
||||||
|
const formRef = ref(null); |
||||||
|
|
||||||
|
async function submit() { |
||||||
|
await formRef.value.validate(); |
||||||
|
await addInspection(form.value); |
||||||
|
feedback.msgSuccess("发布成功"); |
||||||
|
show.value = false; |
||||||
|
getList(); |
||||||
|
} |
||||||
|
|
||||||
|
function handleShowAdd() { |
||||||
|
show.value = true; |
||||||
|
} |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
h5 { |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
.pepole-container > * { |
||||||
|
margin-bottom: 8px; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,469 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<header class="mb-20"> |
||||||
|
<el-form :label-width="114"> |
||||||
|
<el-row> |
||||||
|
<el-col :span="6"> |
||||||
|
<el-form-item label="检测单位"> |
||||||
|
<depart-tree-select v-model="query.departId" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="6"> |
||||||
|
<el-form-item label="任务名称"> |
||||||
|
<el-input |
||||||
|
placeholder="请输入任务名称" |
||||||
|
v-model="query.nickName" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
<div class="flex between"> |
||||||
|
<el-button type="primary" @click="handleShowAdd"> |
||||||
|
<template #icon> |
||||||
|
<icon name="el-icon-Plus" /> |
||||||
|
</template> |
||||||
|
发布任务</el-button |
||||||
|
> |
||||||
|
<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="taskName" /> |
||||||
|
<el-table-column label="检测单位" prop="supDepartName" width="120" /> |
||||||
|
<el-table-column label="检测人员" prop="persons" show-overflow-tooltip /> |
||||||
|
<el-table-column label="抽检人数" prop="totalNumber" width="100" align="center" /> |
||||||
|
<el-table-column |
||||||
|
label="检测时间" |
||||||
|
prop="updateTime" |
||||||
|
width="280" |
||||||
|
> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span>{{ row.beginTime }}</span> |
||||||
|
<span>-</span> |
||||||
|
<span>{{ row.endTime }}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="未检测人数" prop="notDetectedNumber" width="100" align="center" /> |
||||||
|
<el-table-column label="未饮酒人数" prop="notDrinkingNumber" width="100" align="center" /> |
||||||
|
<el-table-column label="饮酒人数" prop="drinkNumber" width="100" align="center" /> |
||||||
|
<el-table-column label="操作" width="200"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
|
||||||
|
>任务详情</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
|
||||||
|
>检测情况</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
<div class="flex end mt-8"> |
||||||
|
<el-pagination |
||||||
|
@size-change="getList" |
||||||
|
@current-change="getList" |
||||||
|
:page-sizes="[10, 20, 50]" |
||||||
|
v-model:page-size="query.size" |
||||||
|
v-model:current-page="query.current" |
||||||
|
layout="total, sizes, prev, pager, next" |
||||||
|
:total="total" |
||||||
|
> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog |
||||||
|
title="发布任务" |
||||||
|
v-model="show" |
||||||
|
width="1076px" |
||||||
|
top="3vh" |
||||||
|
style="margin-bottom: 0" |
||||||
|
> |
||||||
|
<el-scrollbar max-height="76vh"> |
||||||
|
<el-form |
||||||
|
:label-width="150" |
||||||
|
ref="formRef" |
||||||
|
:model="form" |
||||||
|
style="min-height: 76vh" |
||||||
|
> |
||||||
|
<el-form-item |
||||||
|
label="任务名称" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请输入任务名称', |
||||||
|
trigger: ['blur'], |
||||||
|
}" |
||||||
|
prop="taskName" |
||||||
|
> |
||||||
|
<el-input |
||||||
|
v-model="form.taskName" |
||||||
|
placeholder="请输入任务名称" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="检测单位" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
prop="supDepartId" |
||||||
|
> |
||||||
|
<div style="width: 300px"> |
||||||
|
<depart-tree-select v-model="form.supDepartId" /> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="检测人员" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
prop="persons" |
||||||
|
> |
||||||
|
<police-picker v-model="form.persons" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="检测时间" |
||||||
|
prop="times" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
> |
||||||
|
<div style="width: 800px"> |
||||||
|
<el-date-picker |
||||||
|
v-model="form.times" |
||||||
|
type="datetimerange" |
||||||
|
range-separator="-" |
||||||
|
start-placeholder="开始时间" |
||||||
|
end-placeholder="结束时间" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
label="检测对象" |
||||||
|
prop="dataGenerationMethod" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请选择', |
||||||
|
}" |
||||||
|
> |
||||||
|
<el-radio-group v-model="form.dataGenerationMethod"> |
||||||
|
<el-radio value="Excel导入人员">Excel导入人员</el-radio> |
||||||
|
<el-radio value="自定义人员">自定义人员</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<template v-if="form.dataGenerationMethod === 'Excel导入人员'"> |
||||||
|
<el-upload |
||||||
|
drag |
||||||
|
:multiple="false" |
||||||
|
:auto-upload="false" |
||||||
|
:show-file-list="false" |
||||||
|
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" |
||||||
|
> |
||||||
|
<el-icon class="el-icon--upload" |
||||||
|
><upload-filled |
||||||
|
/></el-icon> |
||||||
|
<div class="el-upload__text"> |
||||||
|
<p>点击或拖拽文件到此区域上传</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</template> |
||||||
|
<template v-if="form.dataGenerationMethod === '自定义人员'"> |
||||||
|
<h5>筛选条件</h5> |
||||||
|
<el-row> |
||||||
|
<el-col :span="8"> |
||||||
|
<el-form-item |
||||||
|
label="被抽检次数少于" |
||||||
|
prop="filterMinSupNumber" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请输入', |
||||||
|
}" |
||||||
|
> |
||||||
|
<el-input-number |
||||||
|
controls-position="right" |
||||||
|
style="width: 80px" |
||||||
|
v-model="form.filterMinSupNumber" |
||||||
|
/> |
||||||
|
<span class="ml-8">次</span> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="8"> |
||||||
|
<el-form-item |
||||||
|
label="距最后一次检测时间" |
||||||
|
prop="filterLastDays" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请输入距最后一次检测时间', |
||||||
|
}" |
||||||
|
> |
||||||
|
<el-input-number |
||||||
|
controls-position="right" |
||||||
|
style="width: 80px" |
||||||
|
v-model="form.filterLastDays" |
||||||
|
/> |
||||||
|
<span class="ml-8">天</span> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="8"> |
||||||
|
<el-form-item label="有无饮酒历史"> |
||||||
|
<el-radio-group |
||||||
|
v-model="form.filterAlcoholHistory" |
||||||
|
> |
||||||
|
<el-radio :value="true">有</el-radio> |
||||||
|
<el-radio :value="false">无</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="8"> |
||||||
|
<el-form-item |
||||||
|
label="抽检人数" |
||||||
|
prop="filterPeopleNumber" |
||||||
|
:rules="{ |
||||||
|
required: true, |
||||||
|
message: '请输入抽检人数', |
||||||
|
}" |
||||||
|
> |
||||||
|
<el-input-number |
||||||
|
controls-position="right" |
||||||
|
style="width: 80px" |
||||||
|
v-model="form.filterPeopleNumber" |
||||||
|
/> |
||||||
|
<span class="ml-8">人</span> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<div class="flex between v-center"> |
||||||
|
<h5>被抽检对象</h5> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
plain |
||||||
|
size="small" |
||||||
|
@click="form.filterPeopleConditions.push({})" |
||||||
|
> |
||||||
|
<template #icon> |
||||||
|
<icon name="el-icon-Plus" /> |
||||||
|
</template> |
||||||
|
添加部门</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<div |
||||||
|
class="flex between mb-10" |
||||||
|
v-for="(item, index) in form.filterPeopleConditions" |
||||||
|
:key="index" |
||||||
|
> |
||||||
|
<div class="flex gap"> |
||||||
|
<div> |
||||||
|
<depart-tree-select |
||||||
|
style="width: 280px" |
||||||
|
v-model="item.departId" |
||||||
|
@change=" |
||||||
|
() => { |
||||||
|
handleGetPersonNumber(item); |
||||||
|
} |
||||||
|
" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<el-select |
||||||
|
v-model="item.personType" |
||||||
|
multiple |
||||||
|
clearable |
||||||
|
style="width: 280px" |
||||||
|
@change=" |
||||||
|
() => { |
||||||
|
handleGetPersonNumber(item); |
||||||
|
} |
||||||
|
" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="item in dict.personType" |
||||||
|
:key="item.id" |
||||||
|
:label="item.dictLabel" |
||||||
|
:value="item.dictValue" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
<el-select |
||||||
|
v-model="item.position" |
||||||
|
style="width: 180px" |
||||||
|
multiple |
||||||
|
clearable |
||||||
|
@change=" |
||||||
|
() => { |
||||||
|
handleGetPersonNumber(item); |
||||||
|
} |
||||||
|
" |
||||||
|
> |
||||||
|
<el-option value="正职">正职</el-option> |
||||||
|
<el-option value="副职">副职</el-option> |
||||||
|
<el-option value="">无职位</el-option> |
||||||
|
</el-select> |
||||||
|
<span class="ml-20"> |
||||||
|
<span |
||||||
|
>人数:{{ |
||||||
|
item.polices?.length || 0 |
||||||
|
}}人</span |
||||||
|
> |
||||||
|
<span></span> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<el-button |
||||||
|
type="danger" |
||||||
|
plain |
||||||
|
@click=" |
||||||
|
form.filterPeopleConditions.splice(index, 1) |
||||||
|
" |
||||||
|
>删除</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex between v-center"> |
||||||
|
<h5>被抽检对象名单</h5> |
||||||
|
<div> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
plain |
||||||
|
size="small" |
||||||
|
@click="handleGenPeople" |
||||||
|
v-if="form.peoples.length > 0" |
||||||
|
>重新生成抽检对象</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="text-center" v-if="form.peoples.length === 0"> |
||||||
|
<el-button type="primary" plain @click="handleGenPeople" |
||||||
|
>生成抽检对象</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
<div class="flex gap wrap pepole-container"> |
||||||
|
<el-tag v-for="item in form.peoples" :key="item" |
||||||
|
>{{ item.name }}-{{ item.empNo }}</el-tag |
||||||
|
> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</el-form> |
||||||
|
</el-scrollbar> |
||||||
|
<footer class="flex end mt-20"> |
||||||
|
<el-button type="primary" @click="submit" size="large" |
||||||
|
>发布</el-button |
||||||
|
> |
||||||
|
</footer> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
<script setup> |
||||||
|
import { listTestingAlcohol, addTestingAlcohol, getPersonNumber } from "@/api/mobileSupervision/testingAlcohol"; |
||||||
|
import feedback from "@/utils/feedback"; |
||||||
|
import useCatchStore from "@/stores/modules/catch"; |
||||||
|
|
||||||
|
const catchStore = useCatchStore(); |
||||||
|
const dict = catchStore.getDicts([, "personType"]); |
||||||
|
|
||||||
|
const list = ref([]); |
||||||
|
const query = ref({ |
||||||
|
current: 1, |
||||||
|
size: 10, |
||||||
|
}); |
||||||
|
const total = ref(0); |
||||||
|
function getList() { |
||||||
|
listTestingAlcohol(query.value).then((data) => { |
||||||
|
list.value = data.records; |
||||||
|
total.value = data.total; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function reset() { |
||||||
|
query.value = { |
||||||
|
current: 1, |
||||||
|
size: 10, |
||||||
|
}; |
||||||
|
getList(); |
||||||
|
} |
||||||
|
|
||||||
|
getList(); |
||||||
|
|
||||||
|
const show = ref(false); |
||||||
|
|
||||||
|
const form = ref({ |
||||||
|
dataGenerationMethod: "自定义人员", |
||||||
|
filterMinSupNumber: 10, |
||||||
|
filterLastDays: 60, |
||||||
|
filterAlcoholHistory: false, |
||||||
|
filterPeopleNumber: 10, |
||||||
|
filterPeopleConditions: [], |
||||||
|
peoples: [], |
||||||
|
}); |
||||||
|
const formRef = ref(null); |
||||||
|
|
||||||
|
async function submit() { |
||||||
|
await formRef.value.validate(); |
||||||
|
await addTestingAlcohol(form.value); |
||||||
|
feedback.msgSuccess('发布成功') |
||||||
|
show.value = false; |
||||||
|
getList() |
||||||
|
} |
||||||
|
|
||||||
|
async function handleGetPersonNumber(item) { |
||||||
|
console.log(item); |
||||||
|
if (item.departId) { |
||||||
|
item.polices = await getPersonNumber(item); |
||||||
|
} else { |
||||||
|
item.polices = []; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function handleShowAdd() { |
||||||
|
show.value = true; |
||||||
|
} |
||||||
|
|
||||||
|
function handleGenPeople() { |
||||||
|
const sum = form.value.filterPeopleConditions |
||||||
|
.filter((item) => item.polices) |
||||||
|
.map((item) => item.polices.length) |
||||||
|
.reduce((a, b) => a + b); |
||||||
|
const peoples = []; |
||||||
|
form.value.filterPeopleConditions |
||||||
|
.filter((item) => item.polices) |
||||||
|
.forEach((item) => { |
||||||
|
const count = |
||||||
|
(item.polices.length / sum) * form.value.filterPeopleNumber; |
||||||
|
for (let i = 0; i < count; i++) { |
||||||
|
addPepole(peoples, item.polices); |
||||||
|
} |
||||||
|
}); |
||||||
|
form.value.peoples = peoples; |
||||||
|
} |
||||||
|
|
||||||
|
function addPepole(peoples, polices) { |
||||||
|
const randomIndex = Math.floor(Math.random() * polices.length); |
||||||
|
console.log(randomIndex); |
||||||
|
const item = polices[randomIndex]; |
||||||
|
if (!peoples.includes(item)) { |
||||||
|
peoples.push(item); |
||||||
|
} else { |
||||||
|
addPepole(peoples, polices); |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
h5 { |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
.pepole-container > * { |
||||||
|
margin-bottom: 8px; |
||||||
|
} |
||||||
|
</style> |
||||||
Loading…
Reference in new issue