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.
791 lines
26 KiB
791 lines
26 KiB
<template> |
|
<div class="flex between mb-20 card"> |
|
<div class="flex gap-20"> |
|
<div |
|
class="flex gap v-center" |
|
v-for="item in data.coHandlingPolices" |
|
:key="item.empNo" |
|
> |
|
<icon name="local-icon-police" :size="20" /> |
|
<span>{{ item.name }}</span> |
|
<span>{{ item.empNo }}</span> |
|
<span>{{ item.mobile }}</span> |
|
</div> |
|
</div> |
|
<el-button |
|
type="primary" |
|
size="small" |
|
@click="coHandlingPoliceShow = true" |
|
>编辑协办民警</el-button |
|
> |
|
</div> |
|
<header class="flex mb-20"> |
|
<template v-for="(item, index) in threeSteps" :key="item.index"> |
|
<div |
|
class="step flex center v-center" |
|
:active="activeStep === item.index" |
|
:completed="item.index < step" |
|
:diabled="item.index > step" |
|
@click="handleChangeTab(item.index)" |
|
> |
|
<span class="mr-8">{{ index + 1 }}</span> |
|
<span>{{ item.name }}</span> |
|
</div> |
|
</template> |
|
</header> |
|
<el-form :label-width="170" :model="form" :rules="rules" ref="formRef"> |
|
<template v-if="activeStep === 1"> |
|
<el-row> |
|
<el-col :span="12"> |
|
<el-form-item label="联系民警" prop="contactPolice"> |
|
<police-select v-model:data="form.contactPolice" /> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="12"> |
|
<el-form-item label="职位"> |
|
<span>{{ form.contactPolice?.postTitle }}</span> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="12"> |
|
<el-form-item label="是否取得联系" prop="contactFlag"> |
|
<el-radio-group v-model="form.contactFlag"> |
|
<el-radio :label="true" size="large" |
|
>取得联系</el-radio |
|
> |
|
<el-radio :label="false" size="large" |
|
>未取得联系</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="12"> |
|
<el-form-item label="联系时间" prop="contactTime"> |
|
<el-date-picker |
|
type="datetime" |
|
v-model="form.contactTime" |
|
value-format="YYYY-MM-DD HH:mm:ss" |
|
@change="handleTimeChange" |
|
style="width: 100%" |
|
/> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="12"> |
|
<el-form-item label="联系时长"> |
|
<span>{{ formatTimeText(form.contactDuration) }}</span> |
|
<span |
|
v-if="form.contactDuration" |
|
:danger="form.contactDuration > limitedTime" |
|
class="ml-4" |
|
>({{ |
|
form.contactDuration > limitedTime |
|
? "已超时" |
|
: "未超时" |
|
}})</span |
|
> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
</template> |
|
<template v-if="activeStep === 2"> |
|
<el-row> |
|
<el-form-item label="接访形式" prop="interviewType"> |
|
<el-select |
|
v-model="form.interviewType" |
|
style="width: 450px" |
|
> |
|
<el-option |
|
v-for="item in dictData.interview_type" |
|
:key="item.value" |
|
:label="item.name" |
|
:value="item.value" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="12" prop="interviewIsLeader"> |
|
<el-form-item label="是否接访一把手"> |
|
<el-radio-group v-model="form.interviewIsLeader"> |
|
<el-radio :label="true" size="large">是</el-radio> |
|
<el-radio :label="false" size="large">否</el-radio> |
|
</el-radio-group> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="12" prop="interviewPoliceEmpNo"> |
|
<el-form-item label="接访领导" prop="interviewPoliceEmpNo"> |
|
<LeaderSelect |
|
v-model="form.interviewPoliceEmpNo" |
|
@change="handleSelect" |
|
leader-type="all" |
|
/> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-form-item |
|
label="接访情况" |
|
prop="interviewDetails" |
|
style="width: 100%" |
|
> |
|
<el-input |
|
type="textarea" |
|
v-model="form.interviewDetails" |
|
:rows="5" |
|
style="width: 100%" |
|
/> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="12"> |
|
<el-form-item label="上传佐证" prop="interviewAttachments"> |
|
<Upload v-model="form.interviewAttachments" /> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="12"> |
|
<el-form-item label="佐证证明材料说明"> |
|
<p> |
|
当面接访/视频接访,请上传接访照片; 电话接访, |
|
请上传录音文件。 |
|
</p> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
</template> |
|
<template v-if="activeStep === 3"> |
|
<el-row> |
|
<el-form-item |
|
label="核办结果" |
|
prop="verifyDetails" |
|
style="width: 100%" |
|
> |
|
<el-input |
|
type="textarea" |
|
v-model="form.verifyDetails" |
|
:rows="5" |
|
style="width: 100%" |
|
/> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-form-item label="是否属实" prop="verifyIsTrue"> |
|
<el-radio-group v-model="form.verifyIsTrue"> |
|
<el-radio |
|
v-for="item in dictData.verify_is_true" |
|
:key="item.name" |
|
:label="item.value" |
|
size="large" |
|
>{{ item.name }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
</el-row> |
|
<el-divider /> |
|
<div |
|
v-if=" |
|
form.verifyIsTrue === '属实' || |
|
form.verifyIsTrue === '基本属实' |
|
" |
|
> |
|
<el-row> |
|
<el-form-item label="被举报人"> |
|
<div> |
|
<div |
|
class="flex between gap mb-10" |
|
v-for="(item, index) in reportedPolices" |
|
:key="index" |
|
> |
|
<el-tree-select |
|
v-model="item.deptId" |
|
:data="depts" |
|
clearable |
|
filterable |
|
node-key="id" |
|
:props="{ value: 'id', label: 'name' }" |
|
check-strictly |
|
placeholder="请选择部门" |
|
@change="handleChangeDept" |
|
:default-expanded-keys="getExpandedKeys()" |
|
/> |
|
|
|
<el-select |
|
v-model="item.empNo" |
|
style="width: 280px" |
|
@change=" |
|
(val) => handleChangePolice(val, index) |
|
" |
|
filterable |
|
> |
|
<el-option |
|
v-for="item in polices" |
|
:key="item.id" |
|
:value="item.empNo" |
|
:label="item.name" |
|
>{{ |
|
item.name + " " + item.empNo |
|
}}</el-option |
|
></el-select |
|
> |
|
<div style="font-size: 12px; min-width: 200px"> |
|
<span v-if="item.empNo"> |
|
<span class="mr-4">警号</span> |
|
<span class="mr-4">{{ |
|
item.empNo |
|
}}</span> |
|
</span> |
|
<span v-if="item.gender"> |
|
<span class="mr-4">性别</span> |
|
<span class="mr-4">{{ |
|
item.gender |
|
}}</span> |
|
</span> |
|
<span v-if="item.birthday"> |
|
<span class="mr-4">出生年月</span> |
|
<span>{{ item.birthday }}</span> |
|
</span> |
|
</div> |
|
<el-button |
|
type="danger" |
|
plain |
|
@click="reportedPolices.splice(index, 1)" |
|
>删除</el-button |
|
> |
|
</div> |
|
</div> |
|
</el-form-item> |
|
</el-row> |
|
<div class="text-center"> |
|
<el-button |
|
type="primary" |
|
plain |
|
@click="reportedPolices.push({})" |
|
>添加被举报人</el-button |
|
> |
|
</div> |
|
<el-divider /> |
|
<el-row> |
|
<el-form-item label="查证属实问题" prop="verifyProblem"> |
|
<el-checkbox-group v-model="form.verifyProblem"> |
|
<el-checkbox |
|
v-for="item in dictData.verify_problem" |
|
:key="item.value" |
|
:label="item.name" |
|
:value="item.value" |
|
/> |
|
</el-checkbox-group> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-form-item |
|
label="是否需要问责" |
|
prop="verifyNeedAccountability" |
|
> |
|
<el-radio-group v-model="form.verifyNeedAccountability"> |
|
<el-radio :label="true" size="large">是</el-radio> |
|
<el-radio :label="false" size="large">否</el-radio> |
|
</el-radio-group> |
|
</el-form-item> |
|
</el-row> |
|
<el-row v-if="form.verifyNeedAccountability"> |
|
<el-form-item label="责任追究"> |
|
<el-checkbox-group v-model="form.verifyPunish"> |
|
<el-checkbox |
|
v-for="item in dictData.verify_punish" |
|
:key="item.value" |
|
:label="item.name" |
|
:value="item.value" |
|
/> |
|
</el-checkbox-group> |
|
</el-form-item> |
|
</el-row> |
|
</div> |
|
<el-row> |
|
<el-form-item |
|
label="群众反应事项解决情况" |
|
prop="verifyIsResolved" |
|
> |
|
<el-radio-group v-model="form.verifyIsResolved"> |
|
<el-radio :label="true" size="large">已解决</el-radio> |
|
<el-radio :label="false" size="large">未解决</el-radio> |
|
</el-radio-group> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-form-item label="办理反馈情况" prop="verifyFeedback"> |
|
<el-radio-group v-model="form.verifyFeedback"> |
|
<el-radio |
|
v-for="item in dictData.satisfaction_status" |
|
:key="item.name" |
|
:label="item.value" |
|
size="large" |
|
>{{ item.name }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="12"> |
|
<el-form-item |
|
label="回访人姓名" |
|
prop="verifyFollowupPolice" |
|
> |
|
<police-select |
|
v-model:data="form.verifyFollowupPolice" |
|
/> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="12"> |
|
<el-form-item label="回访人电话"> |
|
<span>{{ form.verifyFollowupPolice?.mobile }}</span> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-form-item label="回访人警号"> |
|
<span>{{ form.verifyFollowupPolice?.empNo }}</span> |
|
</el-form-item> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="12"> |
|
<el-form-item label="上传佐证" prop="verifyAttachments"> |
|
<Upload v-model="form.verifyAttachments" /> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="12"> |
|
<el-form-item label="佐证材料说明"> |
|
<div style="line-height: 1.5"> |
|
请上传《核查办理报告》、《处理反馈表》及相关的法律文件(比如:受案回执、立案决定书、不予立案决定书等)和佐证材料(比如:谈话笔录、调解协议等)。 |
|
</div> |
|
<div> |
|
<a |
|
:href="`${VITE_API_URL}/api/file/download/template/《核查办理报告》.doc`" |
|
target="_blank" |
|
class="link" |
|
>《核查办理报告》 下载</a |
|
> |
|
<a |
|
:href="`${VITE_API_URL}/api/file/download/template/《处理反馈表》.doc`" |
|
target="_blank" |
|
class="link" |
|
>《处理反馈表》 下载</a |
|
> |
|
</div> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
</template> |
|
</el-form> |
|
|
|
<CoHandlingPoliceEdit |
|
v-model:show="coHandlingPoliceShow" |
|
v-model:data="data.coHandlingPolices" |
|
/> |
|
</template> |
|
<script setup> |
|
import CoHandlingPoliceEdit from "./CoHandlingPoliceEdit.vue"; |
|
|
|
import { listByThree, deptAll } from "@/api/org/department"; |
|
|
|
import { allLists } from "@/api/perms/admin"; |
|
import { timeDiffSeconds, formatTimeText } from "@/utils/util"; |
|
import { useDictData } from "@/hooks/useDictOptions"; |
|
import feedback from "@/utils/feedback"; |
|
|
|
const { VITE_API_URL } = process.env; |
|
|
|
const { dictData } = useDictData([ |
|
"interview_type", |
|
"verify_problem", |
|
"verify_punish", |
|
"satisfaction_status", |
|
"verify_is_true", |
|
]); |
|
|
|
const coHandlingPoliceShow = ref(false); |
|
|
|
const rules = { |
|
contactPolice: [ |
|
{ |
|
required: true, |
|
message: "请选择联系民警", |
|
}, |
|
], |
|
contactFlag: [ |
|
{ |
|
required: true, |
|
message: "请选择是否联系群众", |
|
}, |
|
], |
|
contactTime: [ |
|
{ |
|
required: true, |
|
message: "请选择联系时间", |
|
}, |
|
], |
|
// 接访群众 |
|
interviewType: [ |
|
{ |
|
required: true, |
|
message: "请选择接访形式", |
|
}, |
|
], |
|
interviewIsLeader: [ |
|
{ |
|
required: true, |
|
message: "请选择是否一把手接访", |
|
}, |
|
], |
|
interviewPoliceEmpNo: [ |
|
{ |
|
required: true, |
|
message: "请选择接访领导", |
|
}, |
|
], |
|
interviewDetails: [ |
|
{ |
|
required: true, |
|
message: "请填写接访情况", |
|
}, |
|
], |
|
interviewAttachments: [ |
|
{ |
|
required: true, |
|
message: "请上传佐证", |
|
}, |
|
], |
|
// 核查办理 |
|
verifyDetails: [ |
|
{ |
|
required: true, |
|
message: "请填写核办结果", |
|
}, |
|
], |
|
verifyIsTrue: [ |
|
{ |
|
required: true, |
|
message: "请选择是否属实", |
|
}, |
|
], |
|
verifyProblem: [ |
|
{ |
|
required: true, |
|
message: "请选择查证属实问题", |
|
}, |
|
], |
|
verifyNeedAccountability: [ |
|
{ |
|
required: true, |
|
message: "请选择是否需要问责", |
|
}, |
|
], |
|
verifyIsResolved: [ |
|
{ |
|
required: true, |
|
message: "请选择群众反应事项解决情况", |
|
}, |
|
], |
|
verifyFeedback: [ |
|
{ |
|
required: true, |
|
message: "请选择办理反馈情况", |
|
}, |
|
], |
|
verifyFollowupPolice: [ |
|
{ |
|
required: true, |
|
message: "请选择回访人", |
|
}, |
|
], |
|
verifyAttachments: [ |
|
{ |
|
required: true, |
|
message: "请上传佐证", |
|
}, |
|
], |
|
}; |
|
|
|
const threeSteps = ref([ |
|
{ |
|
key: "contact_writer", |
|
name: "联系群众", |
|
index: 1, |
|
}, |
|
{ |
|
key: "interview_writer", |
|
name: "接访群众", |
|
index: 2, |
|
}, |
|
{ |
|
key: "verify", |
|
name: "核查办理", |
|
index: 3, |
|
}, |
|
]); |
|
|
|
const props = defineProps({ |
|
mail: { |
|
type: Object, |
|
default: {}, |
|
}, |
|
data: { |
|
type: Object, |
|
default: {}, |
|
}, |
|
limitedTime: { |
|
type: Number, |
|
default: 0, |
|
}, |
|
}); |
|
const emits = defineEmits(["update:data"]); |
|
|
|
if (props.mail.simpleFlowFlag) { |
|
threeSteps.value = [ |
|
{ |
|
key: "contact_writer", |
|
name: "联系群众", |
|
index: 1, |
|
}, |
|
{ |
|
key: "verify", |
|
name: "核查办理", |
|
index: 3, |
|
}, |
|
]; |
|
} |
|
|
|
const step = ref(1); |
|
watch( |
|
() => props.mail.id, |
|
() => { |
|
formRef.value.resetFields(); |
|
initForm(); |
|
// 每次改变信件需要重新计算步骤 |
|
resetStep(); |
|
} |
|
); |
|
|
|
const resetStep = () => { |
|
if (props.mail.flowKey === "interview_writer") { |
|
step.value = 2; |
|
} else if (props.mail.flowKey === "verify") { |
|
step.value = 3; |
|
} else step.value = 1; |
|
}; |
|
|
|
watch( |
|
() => props.mail.flowKey, |
|
() => { |
|
updateStep(); |
|
} |
|
); |
|
|
|
watch( |
|
() => props.mail.coHandlingPolices, |
|
(val) => { |
|
updateCoHandlingPolices() |
|
} |
|
); |
|
|
|
if (props.mail.coHandlingPolices) { |
|
updateCoHandlingPolices(); |
|
} |
|
|
|
function updateCoHandlingPolices() { |
|
console.log('updateCoHandlingPolices') |
|
const data = { ...props.data }; |
|
data.coHandlingPolices = props.mail.coHandlingPolices; |
|
emits("update:data", data); |
|
} |
|
|
|
const depts = ref([]); |
|
updateStep(); |
|
function updateStep() { |
|
if (props.mail.flowKey === "interview_writer") { |
|
step.value = 2; |
|
} |
|
if (props.mail.flowKey === "verify") { |
|
step.value = 3; |
|
getDepts(props.mail); |
|
} |
|
} |
|
|
|
const activeStep = computed(() => step.value); |
|
|
|
function handleChangeTab(index) { |
|
if (props.mail.flowKey === "verify") { |
|
step.value = index; |
|
} |
|
} |
|
|
|
function handleTimeChange(val) { |
|
form.value.contactDuration = timeDiffSeconds( |
|
val, |
|
props.mail.flowLimitedLastHandlerTime, |
|
"YYYY-MM-DD HH:mm:ss" |
|
); |
|
} |
|
|
|
function handleSelect(empNo, option) { |
|
form.value.interviewPoliceName = option.name; |
|
} |
|
|
|
function getDepts(mail) { |
|
if (mail.mainDeptLevel === 1) { |
|
deptAll().then((data) => { |
|
depts.value = data; |
|
}); |
|
} |
|
if (mail.mainDeptLevel === 2) { |
|
listByThree().then((data) => { |
|
depts.value = data; |
|
}); |
|
} |
|
if (mail.mainDeptLevel === 3) { |
|
depts.value = []; |
|
depts.value.push({ |
|
id: mail.threeDeptId, |
|
name: mail.threeDeptName, |
|
}); |
|
} |
|
} |
|
const getExpandedKeys = () => { |
|
if ( |
|
depts.value.length && |
|
depts.value[0].children && |
|
depts.value[0].children.length > 0 |
|
) { |
|
return [depts.value[0].id]; |
|
} |
|
return []; |
|
}; |
|
|
|
const polices = ref([]); |
|
function handleChangeDept(deptId) { |
|
allLists({ |
|
deptId, |
|
}).then((data) => { |
|
polices.value = data; |
|
}); |
|
} |
|
|
|
function handleChangePolice(val, index) { |
|
const police = polices.value.filter((item) => item.empNo === val)[0]; |
|
reportedPolices.value[index].gender = police.gender; |
|
reportedPolices.value[index].birthday = police.birthday; |
|
reportedPolices.value[index].name = police.name; |
|
} |
|
|
|
const form = ref({}); |
|
|
|
initForm(); |
|
function initForm() { |
|
form.value = { |
|
contactPolice: props.mail.contactPolice, |
|
contactFlag: props.mail.contactFlag, |
|
contactTime: props.mail.contactTime, |
|
contactDuration: props.mail.contactDuration, |
|
// 接访群众 |
|
interviewType: props.mail.interviewType, |
|
interviewIsLeader: props.mail.interviewIsLeader, |
|
interviewPoliceEmpNo: props.mail.interviewPoliceEmpNo, |
|
interviewDetails: props.mail.interviewDetails, |
|
interviewAttachments: props.mail.interviewAttachments, |
|
// 核查办理 |
|
verifyDetails: props.mail.verifyDetails, |
|
verifyIsTrue: props.mail.verifyIsTrue, |
|
verifyProblem: props.mail.verifyProblem || [], |
|
verifyNeedAccountability: props.mail.verifyNeedAccountability, |
|
verifyIsResolved: props.mail.verifyIsResolved, |
|
verifyFeedback: props.mail.verifyFeedback, |
|
verifyFollowupPolice: props.mail.verifyFollowupPolice, |
|
verifyAttachments: props.mail.verifyAttachments || [], |
|
verifyPunish: props.mail.verifyPunish || [], |
|
}; |
|
} |
|
const reportedPolices = ref([]); |
|
const formRef = ref(); |
|
|
|
function validate() { |
|
return new Promise((resolve, reject) => { |
|
formRef.value.validate((valid) => { |
|
if (valid) { |
|
const verifyReportedPolices = reportedPolices.value.filter( |
|
(item) => item.empNo |
|
); |
|
form.value.verifyReportedPolices = JSON.stringify( |
|
verifyReportedPolices |
|
); |
|
const data = { ...props.data, ...form.value }; |
|
emits("update:data", data); |
|
resolve(true); |
|
} else { |
|
feedback.msgWarning("请检查输入项"); |
|
reject(); |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
function getData() { |
|
return new Promise((resolve, reject) => { |
|
const verifyReportedPolices = reportedPolices.value.filter( |
|
(item) => item.empNo |
|
); |
|
form.value.verifyReportedPolices = JSON.stringify( |
|
verifyReportedPolices |
|
); |
|
const data = { ...props.data, ...form.value }; |
|
emits("update:data", data); |
|
resolve(true); |
|
}); |
|
} |
|
|
|
defineExpose({ |
|
validate, |
|
getData |
|
}); |
|
</script> |
|
<style lang="scss" scoped> |
|
.card { |
|
background: #f4f5ff; |
|
border: 1px solid rgba(195, 202, 245, 1); |
|
padding: 12px 20px; |
|
} |
|
|
|
.step { |
|
width: 100%; |
|
|
|
&[active="true"] { |
|
--setp-background-color: #edf0ff; |
|
--setp-border-color: rgba(195, 202, 245, 1); |
|
--setp-font-color: #162582; |
|
} |
|
|
|
&[completed="true"] { |
|
--setp-font-color: #666; |
|
|
|
&::after { |
|
--setp-border-color: #8191f1; |
|
background-color: var(--primary-color); |
|
} |
|
} |
|
|
|
&[diabled="false"] { |
|
&:hover { |
|
cursor: pointer; |
|
--setp-background-color: #edf0ff; |
|
} |
|
} |
|
} |
|
|
|
span[danger="true"] { |
|
color: var(--danger-color); |
|
} |
|
|
|
p { |
|
margin: 0; |
|
} |
|
</style> |