数字督察一体化平台-前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

787 lines
23 KiB

<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-select clearable v-model="query.taskType">
<el-option
v-for="item in dict.taskType"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="问题描述">
<el-input placeholder="请输入" v-model="query.thingDesc" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="分发状态">
<el-select v-model="query.distributionState" clearable>
<el-option
v-for="item in dict.distributionState"
: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="handleShowGenReport">
生成督察通报
<span v-if="selectRows.length">({{ selectRows.length }})</span></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>
<el-tabs class="demo-tabs" @tab-click="handleTabClick">
<el-tab-pane label="全部" name="0"></el-tab-pane>
<el-tab-pane label="待下发" name="1"></el-tab-pane>
<el-tab-pane label="回收站" name="2"></el-tab-pane>
</el-tabs>
<div class="table-container">
<el-table :data="list" v-loading="loading" @selection-change="handleTableSelect">
<el-table-column type="selection" width="55" />
<el-table-column label="发现时间" prop="createTime" width="150" />
<el-table-column label="录入时间" prop="supTime" width="150" />
<el-table-column label="是否存在问题" width="80" align="center">
<template #default="{ row }">
<span>{{ row.hasProblem ? "是" : "否" }}</span>
</template>
</el-table-column>
<el-table-column label="问题来源" width="120">
<template #default="{ row }">
<span>{{ getDictLable(dict.taskType, row.taskType) }}</span>
</template>
</el-table-column>
<el-table-column
label="涉及人员"
prop="peoples"
width="90"
show-overflow-tooltip
/>
<el-table-column label="涉及单位" prop="departName" show-overflow-tooltip />
<el-table-column label="问题类型" prop="problemType" show-overflow-tooltip />
<el-table-column label="问题描述" prop="thingDesc" show-overflow-tooltip />
<el-table-column label="分发状态" width="90" align="center">
<template #default="{ row }">
<span v-if="row.distributionState === '0'">未分发</span>
<span v-if="row.distributionState === '1'">已分发</span>
</template>
</el-table-column>
<el-table-column label="操作" width="300">
<template #default="{ row }">
<el-button type="primary" link @click="showDeatil(row)">问题详情</el-button>
<el-button
@click="upProblemFun(row)"
type="primary"
link
v-if="row.distributionState === '0'"
>
编辑
</el-button>
<el-button
v-if="row.distributionState === '0'"
type="primary"
link
@click="issueMatterFun(row)"
>问题下发</el-button>
<el-button
:type="row.problemState == '1' ? 'danger' : 'primary'"
link
@click="upProblemStateFun(row)"
>
{{ row.problemState == "1" ? "删除" : "恢复" }}
</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">
<div style="min-height: 500px">
<div class="row">
<div class="col col-12">
<label>发现时间</label>
<span>{{ activeRow.createTime }}</span>
</div>
<div class="col col-12">
<label>问题来源</label>
<span>{{ getDictLable(dict.taskType, activeRow.taskType) }}</span>
</div>
<div class="col col-12">
<label>涉及单位</label>
<span>{{ activeRow.departName }}</span>
</div>
<div class="col col-12">
<label>涉及人员</label>
<span v-if="activeRow.peoples">
<el-tag v-for="(item, index) in JSON.parse(activeRow.peoples)" :key="index">
{{ item.name }}
</el-tag>
</span>
</div>
<div class="col col-12">
<label>录入人</label>
<span>{{ activeRow.createName || "/" }}</span>
</div>
<div class="col col-24">
<label>问题类型</label>
<span>{{ activeRow.problemType || "/" }}</span>
</div>
<div class="col col-24">
<label>问题描述</label>
<span>{{ activeRow.thingDesc }}</span>
</div>
<div class="col col-12">
<label>分发状态</label>
<span>{{
getDictLable(dict.distributionState, activeRow.distributionState)
}}</span>
</div>
<div class="col col-12" v-if="activeRow.distributionState === '1'">
<label>下发人</label>
<span>{{ activeRow.issueUserName || "/" }}</span>
</div>
<div class="col col-24">
<label>上传附件</label>
<file-list :files="activeRow.files ? JSON.parse(activeRow.files) : []" />
</div>
</div>
</div>
</el-dialog>
<el-dialog
@close="addClose"
title="任务分发"
v-model="distributeShow"
width="50vw"
top="2vh"
style="margin-bottom: 0"
>
<el-form
:label-width="120"
ref="formRefs"
:model="issueForm"
v-loading="issueLoading"
>
<el-form-item
label="任务名称"
prop="taskName"
:rules="{
required: true,
message: '请输入任务名称',
}"
>
<el-input
v-model="issueForm.taskName"
style="width: 280px"
placeholder="请输入"
/>
</el-form-item>
<el-form-item label="指定办理单位" prop="handleDepartId">
<div class="flex gap">
<div style="width: 280px">
<depart-tree-select v-model="issueForm.handleDepartId" />
</div>
<div class="tips mt-10">
<p>指定具体办理单位 指将问题分派给哪个单位办理。</p>
</div>
</div>
</el-form-item>
<el-form-item
label="业务类别"
prop="businessTypeCode"
:rules="{
required: true,
message: '请选择业务类别',
trigger: ['blur'],
}"
>
<el-select v-model="issueForm.businessTypeCode" style="width: 280px">
<el-option
v-for="item in dict.businessType"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item
label="涉嫌问题"
prop="involveProblem"
:rules="{
required: true,
message: '请选择涉嫌问题',
trigger: ['blur'],
}"
>
<el-select
v-model="issueForm.involveProblem"
multiple
clearable
style="width: 280px"
>
<el-option
v-for="item in dict.suspectProblem"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item label="涉及警种" prop="policeType">
<el-select v-model="issueForm.policeType" clearable style="width: 280px">
<el-option
v-for="item in dict.policeType"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item
label="办理时限"
prop="timeLimit"
:rules="{
required: true,
message: '请选择办理时限',
}"
>
<time-limit-select
v-model="issueForm.timeLimit"
v-model:maxSignDuration="issueForm.maxSignDuration"
v-model:maxHandleDuration="issueForm.maxHandleDuration"
v-model:maxExtensionDuration="issueForm.maxExtensionDuration"
/>
</el-form-item>
<el-form-item
label="下发流程"
prop="distributionFlow"
:rules="{
required: true,
message: '请选择下发流程',
}"
>
<el-radio-group v-model="issueForm.distributionFlow" class="block">
<el-radio
v-for="item in dict.distributionFlow"
:key="item.dictCode"
:value="item.dictValue"
>{{ item.dictLabel }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item
label="审核流程"
prop="approvalFlow"
:rules="{
required: true,
message: '请选择审核流程',
}"
>
<el-radio-group v-model="issueForm.approvalFlow">
<el-radio
v-for="item in dict.approvalFlow"
:key="item.dictCode"
:value="item.dictValue"
>{{ item.dictLabel }}{{ item.remark ? `(${item.remark})` : "" }}</el-radio
>
</el-radio-group>
<div class="tips mt-10">
<p>
三级审核 在问题提交办结时,需经过“所队—>二级机构—>市局”三级审核,通过后方可办结;
</p>
<p>
二级审核 在问题提交办结时,仅需经过“所队—>二级机构”两级审核,通过后即可办结;
</p>
</div>
</el-form-item>
<el-form-item label="附件说明" prop="thingFiles">
<file-upload v-model:files="issueForm.thingFiles" />
</el-form-item>
</el-form>
<footer class="flex end mt-20">
<el-button
type="primary"
size="large"
@click="handleSubmitTask"
v-loading="issueLoading"
>确认下发</el-button
>
</footer>
</el-dialog>
<el-dialog @close="upClose" title="编辑问题" v-model="upShow" width="50vw" top="2vh">
<el-form
:label-width="120"
ref="upFormRefs"
:model="upFormData"
v-loading="upLoading"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="发现时间">
<el-date-picker
value-format="YYYY-MM-DD HH:mm"
time-format="HH:mm"
style="width: 100%"
v-model="upFormData.createTime"
type="datetime"
placeholder="请输入发现时间"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="问题来源">
<el-select clearable v-model="upFormData.taskType" style="width: 100%">
<el-option
v-for="item in dict.taskType"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="涉及单位">
<depart-tree-select v-model="upFormData.departId" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="涉及人员">
<el-select
:remote-method="inputPeopleFun"
:loading="peoplesloading"
filterable
multiple
v-model="upFormData.peopleIds"
>
<el-option
v-for="(item, index) in polices"
:key="index"
:value="item.idCode"
:label="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="问题类型">
<problem-type-select
v-model="upFormData.problemTypeCode"
></problem-type-select>
</el-form-item>
</el-col>
<el-col :span="12"></el-col>
<el-col :span="24">
<el-form-item label="问题描述">
<el-input type="textarea" v-model="upFormData.thingDesc"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<file-upload
style="width: 100%"
:uploadDrag="true"
v-model:files="upFormData.files"
></file-upload>
</el-col>
</el-row>
</el-form>
<footer class="flex end mt-20">
<el-button type="primary" size="large" @click="handleUpData" v-loading="upLoading"
>确认</el-button
>
</footer>
</el-dialog>
<el-dialog title="生成督察通报" v-model="showGenReport" width="1100" top="1vh" style="margin-bottom: 0">
<el-scrollbar height="81vh" style="padding: 10px">
<el-form label-width="148" :model="formData" ref="formRef">
<el-form-item
label="督察通报文件名"
prop=""
:rules="{
required: true,
message: '请输入督察通报文件名',
trigger: ['blur'],
}"
>
<el-input v-model="formData.fileName" />
</el-form-item>
<el-divider />
<h3 style="font-size: 16px">通报内容</h3>
<div class="mb-32">
<div class="flex gap">
<el-input v-model="formData.contents1.title" />
<el-button @click="formData.contents1.list.push({})">
<icon name="el-icon-Plus" />
</el-button>
</div>
<ul style="list-style: circle">
<li v-for="(item, index) in formData.contents1.list" class="mb-16">
<div class="flex gap">
<el-input v-model="item.content" type="textarea" />
<el-button @click="formData.contents1.list.splice(index, 1)">
<icon name="el-icon-Minus" />
</el-button>
</div>
</li>
</ul>
</div>
<div>
<div class="flex gap">
<el-input v-model="formData.contents2.title" />
<el-button @click="formData.contents2.list.push({})">
<icon name="el-icon-Plus" />
</el-button>
</div>
<ul style="list-style: circle">
<li v-for="item in formData.contents2.list" class="mb-16">
<div class="flex gap mb-10">
<el-input v-model="item.title" />
<el-button @click="formData.contents2.list.splice(index, 1)">
<icon name="el-icon-Minus" />
</el-button>
</div>
<div class="flex gap">
<el-input v-model="item.content" type="textarea" />
<div style="width: 46px"></div>
</div>
</li>
</ul>
</div>
</el-form>
</el-scrollbar>
<footer class="flex end">
<!-- <el-button @click="showGenReport = false" size="large">通报预览</el-button> -->
<el-button type="primary" @click="handleGenReport" size="large">生成通报</el-button>
</footer>
</el-dialog>
</template>
<script setup>
import { getToken } from '@/utils/token'
import { BASE_PATH } from "@/api/request";
import { getDictLable } from "@/utils/util";
import {
listTaskProblem,
getTaskProblem,
delTaskProblem,
upProblemState,
upTaskProblem,
} from "@/api/mobileSupervision/taskProblem";
import useCatchStore from "@/stores/modules/catch";
import { TestingAlcoholIssueMatterFun } from "@/api/mobileSupervision/testingAlcohol";
import feedback from "@/utils/feedback";
import { listPoliceData } from "@/api/system/police";
const catchStore = useCatchStore();
const dict = catchStore.getDicts([
"taskType",
"policeType",
"approvalFlow",
"suspectProblem",
"businessType",
"distributionFlow",
"distributionState",
]);
const loading = ref(false);
const upLoading = ref(false);
const peoplesloading = ref(false);
const upShow = ref(false);
const upFormData = ref({});
//任务分发
const distributeShow = ref(false);
const issueForm = ref({});
const issueLoading = ref(false);
const formRefs = ref();
//六项规定督察下发问题
const issueMatterFun = async (row) => {
const data = await getTaskProblem(row.id);
switch (row.taskType) {
case "selfexamination":
issueForm.value.problemVo = data;
break;
case "inspection":
issueForm.value.problemVo = data;
break;
case "testing_alcohol":
issueForm.value.taskId = data.taskId;
issueForm.value.empNo = data.empNo;
break;
case "risk_personal":
issueForm.value.supRecordId = row.id;
break;
default:
issueForm.value.problemVo = data;
break;
}
issueForm.value.tableKey = row.taskType;
distributeShow.value = true;
};
const upQuery = ref({
departBranch: true,
});
const polices = ref();
const getPeoplesFun = async () => {
peoplesloading.value = true;
if (upQuery.value.idCodes) {
delete upQuery.value.idCodes;
}
const res = await listPoliceData(upQuery.value);
polices.value = res.records.map((s) => {
return {
name: s.name,
idCode: s.idCode,
empNo: s.empNo,
};
});
delete upQuery.value.idCodes;
console.log("polices", upFormData.value.peoples);
peoplesloading.value = false;
};
//获取用户表
function inputPeopleFun(val) {
upQuery.value.name = val;
getPeoplesFun();
}
inputPeopleFun();
const handleUpData = async () => {
upLoading.value = true;
const res = await upTaskProblem(upFormData.value);
upShow.value = false;
getList();
upLoading.value = false;
};
const addClose = () => {
issueForm.value = {};
};
const upClose = () => {
upFormData.value = {};
};
//下发问题
const handleSubmitTask = async () => {
await formRefs.value.validate();
issueLoading.value = true;
try {
await TestingAlcoholIssueMatterFun(issueForm.value);
} catch (e) {
issueLoading.value = false;
return;
}
issueLoading.value = false;
feedback.msgSuccess("下发成功");
distributeShow.value = false;
getList();
};
const handleTabClick = (tab) => {
query.value.actionType = tab.props.name;
console.log("tab", tab.props.name);
getList();
};
const delProblemsFun = async (row) => {
await feedback.confirm("确定要删除该数据?");
delTaskProblem(row.id).then((res) => {
getList();
});
feedback.msgSuccess("删除成功");
};
async function upProblemStateFun(row) {
await feedback.confirm(
`确定要${
row.problemState == "1" ? "删除" : "恢复"
}该问题项(可在回收站中查看已删除的问题项)?`
);
upProblemState(row.id).then((res) => {
getList();
});
feedback.msgSuccess("操作成功");
}
const query = ref({
actionType: "0",
});
const list = ref([]);
const total = ref(0);
function getList() {
loading.value = true;
listTaskProblem(query.value).then((data) => {
list.value = data.records;
total.value = data.total;
loading.value = false;
});
}
onMounted(() => {
getList();
});
const show = ref(false);
const activeRow = ref({});
async function showDeatil(row) {
show.value = true;
activeRow.value = await getTaskProblem(row.id);
}
const upProblemFun = async (row) => {
upFormData.value = await getTaskProblem(row.id);
upFormData.value.files = JSON.parse(upFormData.value.files);
if (upFormData.value.peoples) {
let lists = JSON.parse(upFormData.value.peoples);
upFormData.value.peoples = lists;
upFormData.value.peopleIds = lists.map((s) => {
return s.idCode;
});
let idCodes = [];
upFormData.value.peoples.forEach((s) => {
if (s.idCode) {
idCodes.push(s.idCode);
}
});
upQuery.value.idCodes = idCodes;
}
upShow.value = true;
};
watch(
() => upFormData.value.departId,
(val) => {
upQuery.value.departId = val;
getPeoplesFun();
},
{ deep: true, immediate: true }
);
watch(
() => upFormData.value.files,
(val) => {
console.log("val", val);
upFormData.value.files = val;
},
{ immediate: true, deep: true }
);
const selectRows = ref([]);
function handleTableSelect(selection) {
selectRows.value = selection;
}
const showGenReport = ref(false);
const formData = ref({});
function handleShowGenReport() {
if (selectRows.value.length === 0) {
feedback.msgWarning("请选择要生成报告的数据");
return;
}
formData.value = {
contents1: {
title: "好的方面",
list: [],
},
contents2: {
title: "发现的问题",
list: [],
},
};
formData.value.contents1.list = selectRows.value
.filter((item) => !item.hasProblem)
.map((item) => {
return {
content: item.thingDesc,
};
});
const problmes = selectRows.value.filter((item) => item.hasProblem)
const set = new Set(problmes.filter(item => item.problemType).map(item => item.problemType.indexOf('/') === -1 ? item.problemType : item.problemType.substring(0, item.problemType.indexOf('/'))))
const arr = [];
set.forEach(item => {
const content = problmes.filter(p => p.problemType && p.problemType.indexOf(item) === 0).map(item => item.thingDesc).join('\n')
arr.push({
title: item,
content: content
})
})
formData.value.contents2.list = arr
showGenReport.value = true;
}
const formRef = ref()
async function handleGenReport() {
await formRef.value.validate();
fetch(`${BASE_PATH}/task/problem/genReport`,
{
method: 'POST',
body: JSON.stringify(formData.value),
headers: {
"Authorization": getToken(),
"Content-Type": "application/json"
}
}).then(response => response.blob())
.then(blob => {
// 创建Blob URL
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = formData.value.fileName + ".docx";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
// 释放Blob URL
URL.revokeObjectURL(blobUrl);
})
.catch(error => console.error('下载失败', error));
}
</script>
<style lang="scss" scoped></style>