数字督察一体化平台-前端
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.
 
 
 
 

779 lines
32 KiB

<template>
<el-dialog
title="问题下发"
width="1024px"
:lock-scroll="false"
top="5vh"
style="margin-bottom: 0"
>
<el-scrollbar
height="78vh"
v-loading="loading"
element-loading-text="问题下发中..."
>
<el-form
label-width="148"
:model="form"
ref="formRef"
style="padding: 0 16px"
>
<h2>问题信息</h2>
<div class="add-negation-container">
<el-row>
<el-col :span="12">
<el-form-item
label="问题来源"
prop="problemSourcesCode"
:rules="{
required: true,
message: '请选择问题来源',
trigger: ['blur'],
}"
>
<dict-select
name="problemSources"
v-model="form.problemSourcesCode"
@change="
(nodeData) =>
(form.problemSources =
nodeData.label)
"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="业务类别"
prop="businessTypeCode"
:rules="{
required: true,
message: '请选择业务类别',
trigger: ['blur'],
}"
>
<el-select
v-model="form.businessTypeCode"
>
<el-option
v-for="item in dict.businessType"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span="12"
>
<el-form-item
label="专项督察"
prop="specialSupervision"
>
<el-select
v-model="form.specialSupervision"
multiple
clearable
collapse-tags
placeholder="请选择专项督察"
>
<el-option
v-for="item in dict.specialSupervision"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col
:span="12"
>
<el-form-item-ext
label="通报期数"
content="如未下拉项中找到对应的通报期数,请前往通报管理中补充对应的通报"
prop="reportNumber"
:rules="{
message: '请输入通报期数',
trigger: ['blur'],
}"
>
<!-- <el-input-->
<!-- placeholder="请输入"-->
<!-- v-model="form.reportNumber"-->
<!-- />-->
<el-select v-model="reportData"
filterable
remote
reserve-keyword
placeholder="请选择通报期数"
:remote-method="getReportListDataFun"
:loading="reportLoading"
>
<el-option
v-for="(item,id) in reportList"
:key="id"
:label="item.reportName"
:value="item.id"
/>
</el-select>
</el-form-item-ext>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item
label="涉及案件/警情编号"
prop="caseNumber"
>
<el-input
v-model="form.caseNumber"
placeholder="请输入"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="涉嫌问题"
prop="involveProblem"
>
<el-select
v-model="form.involveProblem"
multiple
clearable
>
<el-option
v-for="item in dict.suspectProblem"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="问题涉及单位"
prop="involveDepartId"
:rules="{
required: true,
message: '请选择问题涉及单位',
trigger: ['blur'],
}"
>
<depart-tree-select
v-model="form.involveDepartId"
:check-strictly="true"
@node-click="
(row) =>
(form.involveDepartName =
row.shortName)
"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item-ext
label="涉及警种"
content="囊括了市局除分县市局以外的所有业务警种,便于后期统计分析业务条线的问题。"
prop="policeType"
>
<el-select
v-model="form.policeType"
@change="
(val) =>
(form.policeTypeName =
dict.policeType.filter(
(item) =>
item.dictValue === val
)[0].dictLabel)
"
clearable
>
<el-option
v-for="item in dict.policeType"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item-ext>
</el-col>
</el-row>
<el-row
v-if="
ProblemSources_XFTS.includes(
form.problemSourcesCode
)
"
>
<el-col :span="12">
<el-form-item
label="投诉反映人"
prop="responderName"
>
<el-input
placeholder="请输入"
v-model="form.responderName"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="contactPhone">
<el-input
v-model="form.contactPhone"
placeholder="请输入"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item
label="问题发现时间"
prop="discoveryTime"
:rules="{
required: true,
message: '请选择问题发现时间',
trigger: ['blur'],
}"
>
<el-date-picker
v-model="form.discoveryTime"
type="datetime"
placeholder="请选择"
value-format="YYYY-MM-DD HH:mm"
time-format="HH:mm"
style="width: 100%"
:disabled-date="disabledDate"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="问题发生时间"
prop="happenTime"
>
<el-date-picker
v-model="form.happenTime"
type="datetime"
placeholder="请选择"
value-format="YYYY-MM-DD HH:mm"
time-format="HH:mm"
style="width: 100%"
:disabled-date="disabledDate"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item
v-for="(item, index) in form.problems"
:key="index"
:label="`问题${index + 1}`"
>
<div class="flex between v-center" style="width: 100%">
<div class="flex">
<problem-type-select
style="width: 280px"
@change="
(node) =>
handleChangeProblem(node, item)
"
v-model="item.threeLevelCode"
/>
<div style="width: 140px" class="ml-8">
<el-form-item
label-position="top"
:prop="`problems.${index}.threeLevelContentOther`"
:rules="{
required: true,
message: '请输入',
trigger: ['blur'],
}"
style="margin-bottom: 0"
v-if="
item.threeLevelContent === '其他'
"
>
<el-input
placeholder="其他类型详细描述"
v-model="
item.threeLevelContentOther
"
/>
</el-form-item>
</div>
<div style="width: 170px;" class="text-nowrap ml-8">
<span>{{
item.oneLevelContent
? item.oneLevelContent + " / "
: ""
}}</span>
<span>{{
item.twoLevelContent
? item.twoLevelContent + " / "
: ""
}}</span>
<span>{{ item.threeLevelContent }}</span>
</div>
</div>
<el-button
@click="handleRemoveProblem(index)"
plain
type="danger"
size="small"
>
<template #icon>
<icon name="el-icon-Delete" />
</template>
删除问题
</el-button>
</div>
</el-form-item>
<div class="flex center mb-10">
<el-button
@click="handleAddProblem()"
plain
type="primary"
size="small"
>
<template #icon>
<icon name="el-icon-Plus" />
</template>
添加问题
</el-button>
</div>
<el-form-item
label="事情简要描述"
prop="thingDesc"
:rules="{
required: true,
message: '请输入事情简要描述',
trigger: ['blur'],
}"
>
<el-input
type="textarea"
placeholder="请输入"
v-model="form.thingDesc"
:autosize="{ minRows: 4 }"
/>
</el-form-item>
<el-form-item label="督察报告附件" v-if="reportFiles?.length > 0">
<file-list v-model:files="reportFiles" :removeEnable="false" />
</el-form-item>
<el-form-item label="问题附件" prop="thingFiles">
<file-upload
v-model:files="form.thingFiles"
tips="为便于“办理单位”更全面了解问题详情,请上传相关附件,如现场督察、数字督察等相关照片、视频及其他佐证材料。"
/>
</el-form-item>
</div>
<el-divider />
<h2>办理单位</h2>
<div class="add-negation-container">
<el-form-item
label="主办层级"
prop="hostLevel"
:rules="{
required: true,
message: '请选择主办层级',
trigger: ['blur'],
}"
>
<el-select
style="width: 280px"
v-model="form.hostLevel"
@change="handleChangeHostLevel"
>
<el-option
v-for="item in dict.hostLevel"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
<div class="tips mt-10">
<p>
如主办层级 为 市局主办, 则由<span
:danger="form.hostLevel === HostLevel.FIRST"
>督察支队</span
>办理;
</p>
<p>
如主办层级为 二级机构主办,则由<span
:danger="
form.hostLevel === HostLevel.SECOND
"
>督察部门</span
>办理,可进一步下发;
</p>
<p>
如主办层级为 三级机构主办,则由<span
:danger="form.hostLevel === HostLevel.THREE"
>所队</span
>办理。
</p>
</div>
</el-form-item>
<el-form-item
label="指定办理单位"
prop="departId"
:rules="{
required: true,
message: '请选择办理单位',
trigger: ['blur'],
}"
>
<div class="flex gap">
<div style="width: 280px">
<template
v-if="form.hostLevel === HostLevel.THREE"
>
<depart-tree-select
v-model="form.departId"
v-loading="departLoading"
/>
</template>
<el-tree-select
v-else
:data="departs"
:props="{
label: 'shortName',
value: 'id',
}"
node-key="id"
clearable
filterable
v-model="form.departId"
@node-click="handleSelectDepart"
check-strictly
style="width: 280px"
v-loading="departLoading"
/>
</div>
<el-button
type="primary"
@click="handleLinkDepart"
text
v-if="form.hostLevel !== HostLevel.FIRST"
>关联问题涉及单位</el-button
>
</div>
<div class="tips mt-10">
<p>问题涉及单位 指与该问题相关的单位;</p>
<p>指定办理单位 指将问题分派给哪个单位办理。</p>
</div>
</el-form-item>
</div>
<h2>办理时限</h2>
<div class="add-negation-container">
<el-form-item
label="办理时限"
prop="timeLimit"
:rules="{
required: true,
message: '请选择办理时限',
trigger: ['blur'],
}"
>
<time-limit-select
v-model="form.timeLimit"
v-model:maxSignDuration="form.maxSignDuration"
v-model:maxHandleDuration="form.maxHandleDuration"
v-model:maxExtensionDuration="
form.maxExtensionDuration
"
/>
</el-form-item>
</div>
<div>
<h2>审批流程</h2>
<div class="add-negation-container">
<el-form-item
label="审批流程"
prop="approvalFlow"
:rules="{
required: true,
message: '请选择审批流程',
trigger: ['blur'],
}"
>
<el-radio-group
v-model="form.approvalFlow"
v-if="
userStore.user.roleCodes.includes('admin_1')
"
>
<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>
<el-radio-group v-model="form.approvalFlow" v-else>
<el-radio value="2"
>二级审批(所队一>二级机构)</el-radio
>
</el-radio-group>
<div class="tips mt-10">
<p
v-if="
userStore.user.roleCodes.includes(
'admin_1'
)
"
>
三级审核 在问题提交办结时,需经过“所队—>二级机构—>市局”三级审核,通过后方可办结;
</p>
<p>
二级审核 在问题提交办结时,仅需经过“所队—>二级机构”两级审核,通过后即可办结;
</p>
</div>
</el-form-item>
</div>
</div>
</el-form>
</el-scrollbar>
<footer class="flex end">
<el-button @click="emit('close')" size="large">取消</el-button>
<el-button
type="primary"
@click="handleAddNegative"
size="large"
:loading="loading"
>下发问题</el-button
>
</footer>
</el-dialog>
</template>
<script lang="ts" setup>
import moment from "moment";
import {
HostLevel,
TimeLimit,
ApprovalFlow,
ProblemSources,
ProblemSources_XFTS,
} from "@/enums/dictEnums";
import feedback from "@/utils/feedback";
import { addNegative, generateOriginId } from "@/api/work/negative";
import { secondList, listByFirstHost } from "@/api/system/depart";
import useCatchStore from "@/stores/modules/catch";
import { disabledDate } from "@/utils/util";
import useUserStore from "@/stores/modules/user";
import {getListData} from "@/api/superviseReport/superviseReport";
import {computed, watch} from "vue";
const userStore = useUserStore();
const catchStore = useCatchStore();
const dict = catchStore.getDicts([
"businessType",
"suspectProblem",
"policeType",
"hostLevel",
"timeLimit",
"approvalFlow",
"specialSupervision",
]);
const props = defineProps({
modeType: {
type: String,
default: "add",
},
});
const emit = defineEmits(["close"]);
const form = ref({
thingFiles: [],
hostLevel: HostLevel.THREE,
timeLimit: TimeLimit.WORK_137,
approvalFlow: ApprovalFlow.SECOND,
problems: [],
specialSupervision: [],
});
// 专项督察多选转逗号分隔字符串
const specialSupervisionStr = computed(() => {
if (Array.isArray(form.value.specialSupervision)) {
return form.value.specialSupervision.filter(v => v).join(',');
}
return form.value.specialSupervision;
});
watch(
() => form.value.hostLevel,
() => {
getDeparts();
}
);
onMounted(() => {
getDeparts();
});
const formRef = ref(null);
const loading = ref(false);
async function handleAddNegative() {
try {
await formRef.value.validate();
} catch (e) {
feedback.msgWarning("请检查输入项");
throw e;
}
form.value.thingFiles = form.value.thingFiles.filter(
(item) => item.filePath
);
// 专项督察多选转逗号分隔字符串
if (Array.isArray(form.value.specialSupervision)) {
form.value.specialSupervision = form.value.specialSupervision.filter(v => v).join(',');
}
loading.value = true;
try {
await addNegative(form.value);
} catch (e) {
loading.value = false;
return;
}
loading.value = false;
form.value = {
thingFiles: [],
hostLevel: HostLevel.THREE,
timeLimit: TimeLimit.WORK_137,
approvalFlow: ApprovalFlow.SECOND,
specialSupervision: [],
};
reportData.value=null;
feedback.msgSuccess("下发成功");
emit("close");
}
const departs = ref<any[]>([]);
const departLoading = ref(false);
async function getDeparts() {
departLoading.value = true;
if (form.value.hostLevel === HostLevel.FIRST) {
departs.value = await listByFirstHost();
} else if (form.value.hostLevel === HostLevel.SECOND) {
departs.value = await secondList();
}
departLoading.value = false;
}
function handleSelectDepart(row, node) {
form.value.departName = row.shortName;
}
function handleLinkDepart() {
if (form.value.hostLevel === HostLevel.SECOND) {
feedback.msgWarning(
"当前选择二级机构主办,指定办理单位请选择二级机构!"
);
return;
}
form.value.departId = form.value.involveDepartId;
form.value.departName = form.value.involveDepartName;
}
function handleChangeHostLevel(val) {
if (val === HostLevel.FIRST) {
form.value.departId = "";
}
if (val === HostLevel.SECOND) {
form.value.approvalFlow = "3";
}
}
function handleAddProblem() {
form.value.problems.push({});
}
function handleRemoveProblem(index) {
form.value.problems.splice(index, 1);
}
function handleChangeProblem(node, problem) {
if (node.level === 3) {
problem.threeLevelContent = node.label;
problem.oneLevelCode = node.parent.parent.key;
problem.oneLevelContent = node.parent.parent.label;
problem.twoLevelCode = node.parent.key;
problem.twoLevelContent = node.parent.label;
}
}
const reportData = ref(null)
watch(()=>reportData.value,(val)=>{
if(val){
form.value.reportNumber = reportList.value.find(s=>s.id == val).reportName;
form.value.reportId = val;
}
},{deep:true,immediate:true})
const reportQuery = ref({
current: 1,
size: 100,
type: 1
})
const reportList = ref([]);
const reportLoading = ref(false);
const getReportListDataFun =async (val=null)=>{
reportLoading.value=true;
try{
if(val){
reportQuery.value.reportName = val;
}else{
reportQuery.value.reportName =null;
}
console.log('reportQuery.value.reportName',reportQuery.value.reportName)
const res = await getListData(reportQuery.value);
reportList.value=res.records;
reportLoading.value=false;
}catch (e){
reportLoading.value=false;
}
}
const reportFiles = computed(()=> {
if( form.value.reportNumber){
let data= reportList.value.find(s=>s.id === form.value.reportId);
console.log('data',data)
return data.files;
}else{
return []
}
})
</script>
<style lang="scss" scoped>
.add-negation-container {
padding: 0 60px;
}
.tips {
[danger="true"] {
color: var(--danger-color);
}
}
:deep() {
.el-form-item__content {
flex-direction: column;
align-items: flex-start;
}
.block.el-radio-group {
display: block;
.el-radio {
display: block;
}
}
}
</style>