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

534 lines
14 KiB

<template>
<h5>信访办理</h5>
<el-form ref="formRef" :model="form" :label-width="146">
<el-form-item
label="办理环节"
prop="processingStage"
:rules="[{ required: true, message: '请选择办理环节', trigger: 'change' }]"
>
<el-radio-group v-model="form.processingStage">
<el-radio :value="STAGE_INITIAL">初核阶段</el-radio>
<el-radio :value="STAGE_COMPLETION">办结阶段</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="isInitialStage">
<h5>
初核办理
<span style="color: #777; font-size: 12px; margin-left: 10px"
>4个工作日内办结无需上传初核情况</span
>
</h5>
<el-form-item
label="初核工作开展情况"
prop="initWorkDes"
:rules="[{ required: true, message: '请输入初核工作开展情况', trigger: 'blur' }]"
>
<el-input v-model="form.initWorkDes" type="textarea" :autosize="{ minRows: 4 }" />
</el-form-item>
<el-form-item
label="初核发现的问题及下步工作计划"
prop="initProblemPlan"
:rules="[
{
required: true,
message: '请输入初核发现的问题及下步工作计划',
trigger: 'blur',
},
]"
>
<el-input
v-model="form.initProblemPlan"
type="textarea"
:autosize="{ minRows: 4 }"
/>
</el-form-item>
<el-form-item
label="初核结论"
prop="initVerdict"
:rules="[{ required: true, message: '请选择初核结论', trigger: 'change' }]"
>
<el-select v-model="form.initVerdict" clearable style="width: 280px">
<el-option
v-for="item in dict.checkStatus"
:key="item.dictCode"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</template>
<template v-else>
<el-row>
<el-col :span="12">
<el-form-item
label="办结情况"
prop="completionStatus"
:rules="[{ required: true, message: '请选择办结情况', trigger: 'change' }]"
><el-radio-group v-model="form.completionStatus"
><el-radio value="1">程序办结</el-radio
><el-radio value="2">已解决合理诉求</el-radio></el-radio-group
></el-form-item
></el-col
>
<el-col :span="12"
><el-form-item
label="群众认可"
prop="publicRecognition"
:rules="[{ required: true, message: '请选择群众认可', trigger: 'change' }]"
><el-radio-group v-model="form.publicRecognition"
><el-radio value="1">认可</el-radio
><el-radio value="2">不认可</el-radio></el-radio-group
></el-form-item
></el-col
>
</el-row>
<el-form-item
v-if="showPetitionFields"
prop="handlePolices"
label="经办人"
:rules="[{ required: true, validator: validateHandlePolices }]"
>
<div
v-for="(item, index) in form.handlePolices"
:key="index"
class="mb-8 flex gap v-center"
style="width: 100%"
>
<police-select
:depart-id="negative?.handleSecondDepartId"
v-model="item.empNo"
@change="
(police) => {
item.name = police.name;
item.mobile = police.mobile;
}
"
/>
<el-input v-model="item.mobile" placeholder="联系方式" style="width: 240px" />
<el-button
v-if="index === 0"
plain
type="primary"
@click="form.handlePolices.push({ name: '', empNo: '', mobile: '' })"
>新增经办人</el-button
>
<el-button
v-else
plain
type="danger"
@click="form.handlePolices.splice(index, 1)"
>删除</el-button
>
</div>
</el-form-item>
<template
v-if="
sourceNegative.problemSourcesCode === ProblemSources.GJXFPT ||
sourceNegative.problemSourcesCode === ProblemSources.GABXF
"
>
<el-form-item
label="化解情况"
prop="resolveSituation"
:rules="{
required: true,
message: '请选择信访化解情况',
trigger: ['blur'],
}"
>
<el-select
v-model="form.resolveSituation"
clearable
style="width: 240px"
placeholder="请选择信访化解情况"
>
<el-option
v-for="item in dict.resolveSituation"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item
prop="resolveStatus"
label="当前状态"
:rules="{
required: true,
message: '请选择信访当前状态',
trigger: ['blur'],
}"
>
<el-select
v-model="form.resolveStatus"
clearable
style="width: 240px"
placeholder="请选择信访化当前状态"
>
<el-option
v-for="item in dict.resolveStatus"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</template>
<negative-verify ref="negativeVerifyRef" />
</template>
</el-form>
</template>
<script lang="ts" setup>
import { ProblemSources } from "@/enums/dictEnums";
import useCatchStore from "@/stores/modules/catch";
import NegativeVerify from "@/components/negative/verify.vue";
type HandlePolice = {
name: string;
empNo: string;
mobile: string;
};
const STAGE_INITIAL = "0";
const STAGE_COMPLETION = "1";
type ProcessingStage = typeof STAGE_INITIAL | typeof STAGE_COMPLETION;
type VerifySfssForm = {
complaintId?: string;
processingStage: ProcessingStage;
caseNumber: string;
accountabilityTarget: string;
checkStatus: string;
checkStatusCode: string;
checkStatusName: string;
checkStatusDesc: string;
involveDepartId: string;
involveDepartName: string;
initWorkDes: string;
initProblemPlan: string;
initVerdict: string;
completionStatus: string;
publicRecognition: string;
handlePolices: HandlePolice[];
files: any[];
blames: any[];
blameLeaders: any[];
};
const props = defineProps<{ extraDict?: Record<string, any[]> }>();
const emit = defineEmits<{
(e: "stage-change", stage: ProcessingStage): void;
}>();
const catchStore = useCatchStore();
const dict = reactive<Record<string, any[]>>({});
watchEffect(() => {
Object.assign(
dict,
catchStore.getDicts([
"accountabilityTarget",
"checkStatus",
"businessType",
"yesNo",
"handleMethodType",
]) || {},
props.extraDict || {}
);
});
const sourceNegative = inject<any>("negative");
const formRef = ref();
const negativeVerifyRef = ref<InstanceType<typeof NegativeVerify>>();
const createHandlePolice = (): HandlePolice => ({
name: "",
empNo: "",
mobile: "",
});
const createForm = (): VerifySfssForm => ({
complaintId: "",
processingStage: STAGE_INITIAL,
caseNumber: "",
accountabilityTarget: "",
checkStatus: "",
checkStatusCode: "",
checkStatusName: "",
checkStatusDesc: "",
involveDepartId: "",
involveDepartName: "",
initWorkDes: "",
initProblemPlan: "",
initVerdict: "",
completionStatus: "",
publicRecognition: "",
handlePolices: [createHandlePolice()],
files: [],
blames: [],
blameLeaders: [],
});
const form = ref<VerifySfssForm>(createForm());
const currentRow = computed(() => sourceNegative?.value?.currentRow || {});
const isInitialStage = computed(() => form.value.processingStage === STAGE_INITIAL);
const showPetitionFields = computed(() =>
[
ProblemSources.GJXFPT,
ProblemSources.GABXF,
ProblemSources.JZXX,
ProblemSources.XF12337,
].includes(sourceNegative?.value?.problemSourcesCode)
);
debugger
const negative = computed(() => ({
...(sourceNegative?.value || {}),
...clone(form.value),
currentRow: currentRow.value,
}));
provide("negative", negative);
watch(
() => [sourceNegative?.value?.id, currentRow.value?.id],
([negativeId, complaintId]) => {
if (negativeId || complaintId) {
syncFormData();
}
},
{ immediate: true }
);
watch(
() => form.value.processingStage,
(stage) => {
emit("stage-change", stage);
},
{ immediate: true }
);
function clone<T>(value: T): T {
return JSON.parse(JSON.stringify(value));
}
function getStageBySource(row: Record<string, any>) {
const hasInitialReviewData =
Boolean(row?.gwf2) ||
Boolean(row?.initWorkDes) ||
Boolean(row?.initProblemPlan) ||
Boolean(row?.initVerdict);
return sourceNegative?.value?.checkStatusCode ||
sourceNegative?.value?.completionStatus ||
row?.completionStatus ||
sourceNegative?.value?.publicRecognition ||
row?.publicRecognition ||
hasInitialReviewData
? STAGE_COMPLETION
: STAGE_INITIAL;
}
function getHandlePolices() {
const handlePolices = clone(sourceNegative?.value?.handlePolices || []);
return handlePolices.length ? handlePolices : [createHandlePolice()];
}
function syncFormData() {
const row = currentRow.value || {};
const fallbackInvolveDepartId =
sourceNegative?.value?.involveDepartId ||
row?.involveDepartId ||
row?.thirdDepartId ||
row?.secondDepartId ||
"";
const fallbackInvolveDepartName =
sourceNegative?.value?.involveDepartName ||
row?.involveDepartName ||
row?.thirdDepartName ||
row?.secondDepartName ||
"";
form.value = {
...createForm(),
...row,
complaintId: row?.id || sourceNegative?.value?.complaintId || "",
processingStage: getStageBySource(row),
caseNumber: sourceNegative?.value?.caseNumber || row?.caseNumber || "",
accountabilityTarget:
sourceNegative?.value?.accountabilityTarget || row?.accountabilityTarget || "",
checkStatus: sourceNegative?.value?.checkStatus || row?.checkStatus || "",
checkStatusCode: sourceNegative?.value?.checkStatusCode || row?.checkStatusCode || "",
checkStatusName: sourceNegative?.value?.checkStatusName || row?.checkStatusName || "",
checkStatusDesc: sourceNegative?.value?.checkStatusDesc || row?.checkStatusDesc || "",
involveDepartId: fallbackInvolveDepartId,
involveDepartName: fallbackInvolveDepartName,
initWorkDes: row?.initWorkDes || "",
initProblemPlan: row?.initProblemPlan || "",
initVerdict: row?.initVerdict || "",
completionStatus: String(
sourceNegative?.value?.completionStatus ?? row?.completionStatus ?? ""
),
publicRecognition: String(
sourceNegative?.value?.publicRecognition ?? row?.publicRecognition ?? ""
),
handlePolices: getHandlePolices(),
files: clone(sourceNegative?.value?.files || []),
blames: clone(sourceNegative?.value?.blames || []),
blameLeaders: clone(sourceNegative?.value?.blameLeaders || []),
};
}
function mergeVerifyForm(verifyForm: Record<string, any> = {}) {
const baseForm = clone(form.value);
const complaintId =
verifyForm?.complaintId ||
baseForm?.complaintId ||
currentRow.value?.id ||
sourceNegative?.value?.complaintId ||
"";
const involveDepartId =
verifyForm?.involveDepartId ||
baseForm?.involveDepartId ||
sourceNegative?.value?.involveDepartId ||
currentRow.value?.involveDepartId ||
currentRow.value?.thirdDepartId ||
currentRow.value?.secondDepartId ||
"";
const involveDepartName =
verifyForm?.involveDepartName ||
baseForm?.involveDepartName ||
sourceNegative?.value?.involveDepartName ||
currentRow.value?.involveDepartName ||
currentRow.value?.thirdDepartName ||
currentRow.value?.secondDepartName ||
"";
return {
...verifyForm,
...baseForm,
complaintId,
involveDepartId,
involveDepartName,
handlePolices: clone(baseForm.handlePolices),
files: clone(verifyForm.files || baseForm.files || []),
blames: clone(verifyForm.blames || baseForm.blames || []),
blameLeaders: clone(verifyForm.blameLeaders || baseForm.blameLeaders || []),
};
}
function validateHandlePolices(
_: unknown,
value: HandlePolice[],
callback: (error?: Error) => void
) {
if (!value?.length || !value[0]?.name) {
callback(new Error("请选择经办人"));
return;
}
if (!value[0]?.mobile) {
callback(new Error("请输入经办人联系方式"));
return;
}
callback();
}
async function validate() {
await formRef.value?.validate();
const verifyData = await validateNegativeVerify();
return mergeVerifyForm(verifyData);
}
function getData() {
const verifyData = getNegativeVerifyData();
return mergeVerifyForm(verifyData);
}
function getStage() {
return form.value.processingStage;
}
function setStage(stage: ProcessingStage) {
form.value.processingStage = stage;
}
async function validateNegativeVerify() {
if (isInitialStage.value || !negativeVerifyRef.value) {
return {};
}
return await negativeVerifyRef.value.validate();
}
function getNegativeVerifyData() {
if (isInitialStage.value || !negativeVerifyRef.value) {
return {};
}
return negativeVerifyRef.value.getData();
}
defineExpose({ validate, getData, getStage, setStage });
</script>
<style lang="scss" scoped>
.info-container,
.summary-box {
border: 1px solid #eee;
background: #fafcff;
padding: 12px 16px;
border-radius: 6px;
margin-bottom: 12px;
}
.summary-title {
color: var(--el-color-primary);
font-weight: 600;
margin-bottom: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 10px 0;
}
.col {
display: flex;
gap: 8px;
line-height: 22px;
}
.col-12 {
width: 50%;
}
.col-24 {
width: 100%;
}
label {
width: 140px;
color: #666;
flex: 0 0 auto;
}
span {
color: #222;
flex: 1 1 auto;
word-break: break-word;
}
.inline-actions {
display: inline-flex;
align-items: center;
gap: 8px;
}
.repeat-btn {
padding: 0;
}
</style>