局长信箱-内网端(前端)
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

<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>