|
|
|
@ -32,7 +32,8 @@ |
|
|
|
@open-basis-picker="handleOpenBasisPicker" |
|
|
|
@add-basis="handleAddBasis" |
|
|
|
@remove-basis="handleRemoveBasis" |
|
|
|
@add-person="handleAddPerson" /> |
|
|
|
@add-person="handleAddPerson" |
|
|
|
/> |
|
|
|
|
|
|
|
<!-- 底部按钮 --> |
|
|
|
<div class="bottom-buttons"> |
|
|
|
@ -53,49 +54,51 @@ |
|
|
|
@confirm-task-source="handleTaskSourceConfirm" |
|
|
|
@select-person="handleSelectPerson" |
|
|
|
@select-basis="handleSelectBasis" |
|
|
|
@select-time="handleSelectTime" /> |
|
|
|
@select-time="handleSelectTime" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup name="EnforcementRegister"> |
|
|
|
import { ref, reactive, computed, onMounted, onActivated, onDeactivated } from "vue" |
|
|
|
import { useRouter, useRoute } from "vue-router" |
|
|
|
import { showConfirmDialog, showSuccessToast, showToast } from "vant" |
|
|
|
import EnterpriseInfoSection from "@/components/enforcement/nos/EnterpriseInfoSection.vue" |
|
|
|
import EnforcementInfoSection from "@/components/enforcement/nos/EnforcementInfoSection.vue" |
|
|
|
import RegisterPopups from "@/components/enforcement/nos/RegisterPopups.vue" |
|
|
|
import AttachmentTaskSource from "@/components/enforcement/nos/AttachmentTaskSource.vue" |
|
|
|
import { nosAddApi, nosTaskSourceListApi } from "@/api/nos/enfDemo" |
|
|
|
import { toFullFileUrl, toRelativeFilePath } from "@/util/fileUrl" |
|
|
|
|
|
|
|
const router = useRouter() |
|
|
|
const route = useRoute() |
|
|
|
import { ref, reactive, computed, onMounted, onActivated, onDeactivated } from 'vue'; |
|
|
|
import { useRouter, useRoute } from 'vue-router'; |
|
|
|
import { showConfirmDialog, showSuccessToast, showToast } from 'vant'; |
|
|
|
import EnterpriseInfoSection from '@/components/enforcement/nos/EnterpriseInfoSection.vue'; |
|
|
|
import EnforcementInfoSection from '@/components/enforcement/nos/EnforcementInfoSection.vue'; |
|
|
|
import RegisterPopups from '@/components/enforcement/nos/RegisterPopups.vue'; |
|
|
|
import AttachmentTaskSource from '@/components/enforcement/nos/AttachmentTaskSource.vue'; |
|
|
|
import { nosAddApi, nosTaskSourceListApi } from '@/api/nos/enfDemo'; |
|
|
|
import { toFullFileUrl, toRelativeFilePath } from '@/util/fileUrl'; |
|
|
|
|
|
|
|
const router = useRouter(); |
|
|
|
const route = useRoute(); |
|
|
|
|
|
|
|
// ========== 状态定义 ========== |
|
|
|
|
|
|
|
// 补录模式(必填为true) |
|
|
|
const isSignMode = ref(true) |
|
|
|
const isSignMode = ref(true); |
|
|
|
|
|
|
|
/** 创建空的企业信息对象 */ |
|
|
|
const createDefaultEnterpriseData = () => ({ |
|
|
|
enterpriseName: "", |
|
|
|
usciCode: "", |
|
|
|
enterpriseId: "" |
|
|
|
}) |
|
|
|
enterpriseName: '', |
|
|
|
usciCode: '', |
|
|
|
enterpriseId: '' |
|
|
|
}); |
|
|
|
|
|
|
|
// 企业数据 |
|
|
|
const enterpriseData = ref(createDefaultEnterpriseData()) |
|
|
|
const enterpriseData = ref(createDefaultEnterpriseData()); |
|
|
|
|
|
|
|
// 表单数据(字段名与 NosLawEnforcementTaskSaveBO 一致) |
|
|
|
const formData = reactive({ |
|
|
|
lawEnforcementAgency: '', |
|
|
|
lawEnforcementAgency: $globalStore.useCommon.bureauUnitName, |
|
|
|
taskTypeId: null, |
|
|
|
taskSourceId: "", |
|
|
|
lawEnforcementMatters: "", |
|
|
|
checkItemList: [""], |
|
|
|
legalBasis: [""], |
|
|
|
deadline: "", |
|
|
|
taskSourceId: '', |
|
|
|
lawEnforcementMatters: '', |
|
|
|
checkItemList: [''], |
|
|
|
legalBasis: [''], |
|
|
|
deadline: '', |
|
|
|
proclamation: [] |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
// 执法人员 |
|
|
|
const lawEnforcer = ref([ |
|
|
|
@ -105,9 +108,9 @@ const lawEnforcer = ref([ |
|
|
|
lawEnforcerId: $globalStore.useCommon.userId, |
|
|
|
lawEnforcerIdCard: null |
|
|
|
} |
|
|
|
]) |
|
|
|
]); |
|
|
|
|
|
|
|
const additionalLawEnforcers = ref([]) |
|
|
|
const additionalLawEnforcers = ref([]); |
|
|
|
|
|
|
|
// 弹窗显示状态 |
|
|
|
const showPopups = reactive({ |
|
|
|
@ -118,124 +121,135 @@ const showPopups = reactive({ |
|
|
|
person: false, |
|
|
|
basis: false, |
|
|
|
time: false |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
// 当前编辑索引(用于人员和执法依据) |
|
|
|
const currentEditIndex = ref(-1) |
|
|
|
|
|
|
|
const currentEditIndex = ref(-1); |
|
|
|
|
|
|
|
// 选项数据(仅三种类别) |
|
|
|
const categoryOptions = [ |
|
|
|
{ text: "行政检查", value: 1 }, |
|
|
|
{ text: "材料备案", value: 2 }, |
|
|
|
{ text: "材料验证", value: 3 } |
|
|
|
] |
|
|
|
{ text: '行政检查', value: 1 }, |
|
|
|
{ text: '材料备案', value: 2 }, |
|
|
|
{ text: '材料验证', value: 3 }, |
|
|
|
{ text: '巡查', value: 5 } |
|
|
|
]; |
|
|
|
|
|
|
|
// 从列表页带入 tab 时锁定类别 |
|
|
|
const categoryDisabled = ref(false) |
|
|
|
const categoryDisabled = ref(false); |
|
|
|
|
|
|
|
// 切换 tab / 类别时强制刷新执法信息区块(keep-alive 场景) |
|
|
|
const enforcementSectionKey = computed(() => `${route.query.tab || ""}_${formData.taskTypeId}`) |
|
|
|
const enforcementSectionKey = computed(() => `${route.query.tab || ''}_${formData.taskTypeId}`); |
|
|
|
|
|
|
|
const taskTypeName = computed(() => categoryOptions.find((item) => item.value === formData.taskTypeId)?.text || "") |
|
|
|
const taskTypeName = computed(() => categoryOptions.find((item) => item.value === formData.taskTypeId)?.text || ''); |
|
|
|
|
|
|
|
const DRAFT_STORAGE_PREFIX = "nos_add_draft_" |
|
|
|
const lastActiveTab = ref("") |
|
|
|
const DRAFT_STORAGE_PREFIX = 'nos_add_draft_'; |
|
|
|
const lastActiveTab = ref(''); |
|
|
|
|
|
|
|
/** 从路由 query 中读取 tab 参数(兼容数组形式) */ |
|
|
|
const getRouteTabValue = () => { |
|
|
|
const rawTab = route.query.tab |
|
|
|
return Array.isArray(rawTab) ? rawTab[0] : rawTab |
|
|
|
} |
|
|
|
const rawTab = route.query.tab; |
|
|
|
return Array.isArray(rawTab) ? rawTab[0] : rawTab; |
|
|
|
}; |
|
|
|
|
|
|
|
/** 将路由 tab 解析为任务类别 ID(taskTypeId) */ |
|
|
|
const getTabTaskTypeId = () => { |
|
|
|
const tabValue = getRouteTabValue() |
|
|
|
if (tabValue === undefined || tabValue === null || tabValue === "") return null |
|
|
|
const parsedValue = Number(tabValue) |
|
|
|
return Number.isFinite(parsedValue) ? parsedValue : null |
|
|
|
} |
|
|
|
const tabValue = getRouteTabValue(); |
|
|
|
if (tabValue === undefined || tabValue === null || tabValue === '') return null; |
|
|
|
const parsedValue = Number(tabValue); |
|
|
|
return Number.isFinite(parsedValue) ? parsedValue : null; |
|
|
|
}; |
|
|
|
|
|
|
|
const getPageTabKey = () => getRouteTabValue() || "default" |
|
|
|
/** 获取当前页签标识,用于草稿隔离存储 */ |
|
|
|
const getPageTabKey = () => getRouteTabValue() || 'default'; |
|
|
|
|
|
|
|
const getDraftStorageKey = (tab = getPageTabKey()) => `${DRAFT_STORAGE_PREFIX}${tab}` |
|
|
|
/** 生成当前 Tab 对应的 sessionStorage 草稿键名 */ |
|
|
|
const getDraftStorageKey = (tab = getPageTabKey()) => `${DRAFT_STORAGE_PREFIX}${tab}`; |
|
|
|
|
|
|
|
/** 创建表单默认值(含当前用户所属执法单位) */ |
|
|
|
const createDefaultFormData = () => ({ |
|
|
|
lawEnforcementAgency: $globalStore.useCommon.bureauUnitName, |
|
|
|
taskTypeId: null, |
|
|
|
taskSourceId: "", |
|
|
|
lawEnforcementMatters: "", |
|
|
|
checkItemList: [""], |
|
|
|
legalBasis: [""], |
|
|
|
deadline: "", |
|
|
|
taskSourceId: '', |
|
|
|
lawEnforcementMatters: '', |
|
|
|
checkItemList: [''], |
|
|
|
legalBasis: [''], |
|
|
|
deadline: '', |
|
|
|
proclamation: [] |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
/** 默认任务截止时间:次日,格式 YYYY-MM-DD */ |
|
|
|
const getDefaultEnforcementTime = () => { |
|
|
|
const tomorrow = new Date() |
|
|
|
tomorrow.setDate(tomorrow.getDate() + 1) |
|
|
|
return `${tomorrow.getFullYear()}-${String(tomorrow.getMonth() + 1).padStart(2, "0")}-${String(tomorrow.getDate()).padStart(2, "0")}` |
|
|
|
} |
|
|
|
const tomorrow = new Date(); |
|
|
|
tomorrow.setDate(tomorrow.getDate() + 1); |
|
|
|
return `${tomorrow.getFullYear()}-${String(tomorrow.getMonth() + 1).padStart(2, '0')}-${String(tomorrow.getDate()).padStart(2, '0')}`; |
|
|
|
}; |
|
|
|
|
|
|
|
/** uploader 展示用(幂等,可多次调用) */ |
|
|
|
const serializeProclamation = (proclamation = []) => |
|
|
|
proclamation.map((file) => ({ |
|
|
|
url: toFullFileUrl(file?.url || file?.filePath || ""), |
|
|
|
status: file?.status || "done", |
|
|
|
name: file?.name || file?.fileName || "", |
|
|
|
url: toFullFileUrl(file?.url || file?.filePath || ''), |
|
|
|
status: file?.status || 'done', |
|
|
|
name: file?.name || file?.fileName || '', |
|
|
|
isImage: file?.isImage |
|
|
|
})) |
|
|
|
})); |
|
|
|
|
|
|
|
/** 草稿持久化用相对路径,避免 sessionStorage 中重复叠加 /api */ |
|
|
|
const persistProclamationForDraft = (proclamation = []) => |
|
|
|
proclamation.map((file) => ({ |
|
|
|
url: toRelativeFilePath(file?.url || file?.filePath || ""), |
|
|
|
status: file?.status || "done", |
|
|
|
name: file?.name || file?.fileName || "", |
|
|
|
url: toRelativeFilePath(file?.url || file?.filePath || ''), |
|
|
|
status: file?.status || 'done', |
|
|
|
name: file?.name || file?.fileName || '', |
|
|
|
isImage: file?.isImage |
|
|
|
})) |
|
|
|
})); |
|
|
|
|
|
|
|
/** 将草稿/历史字段名统一映射为 formData 结构 */ |
|
|
|
const normalizeFormData = (data = {}) => { |
|
|
|
const categoryNameToId = Object.fromEntries(categoryOptions.map((item) => [item.text, item.value])) |
|
|
|
const checkItemList = data.checkItemList ?? (data.materialRequirements || []).map((item) => (typeof item === "string" ? item : item?.name || "")) |
|
|
|
const categoryNameToId = Object.fromEntries(categoryOptions.map((item) => [item.text, item.value])); |
|
|
|
const checkItemList = data.checkItemList ?? (data.materialRequirements || []).map((item) => (typeof item === 'string' ? item : item?.name || '')); |
|
|
|
|
|
|
|
return { |
|
|
|
lawEnforcementAgency: data.lawEnforcementAgency ?? data.enforcementUnit ?? "", |
|
|
|
lawEnforcementAgency: data.lawEnforcementAgency ?? '', |
|
|
|
taskTypeId: data.taskTypeId ?? categoryNameToId[data.category] ?? null, |
|
|
|
taskSourceId: data.taskSourceId ?? data.taskSource ?? "", |
|
|
|
lawEnforcementMatters: data.lawEnforcementMatters ?? data.enforcementMatter ?? "", |
|
|
|
checkItemList: checkItemList.length ? checkItemList : [""], |
|
|
|
legalBasis: [...(data.legalBasis || data.enforcementBases || [""])], |
|
|
|
deadline: data.deadline ?? data.enforcementTime ?? "", |
|
|
|
taskSourceId: data.taskSourceId ?? data.taskSource ?? '', |
|
|
|
lawEnforcementMatters: data.lawEnforcementMatters ?? data.enforcementMatter ?? '', |
|
|
|
checkItemList: checkItemList.length ? checkItemList : [''], |
|
|
|
legalBasis: [...(data.legalBasis || data.enforcementBases || [''])], |
|
|
|
deadline: data.deadline ?? data.enforcementTime ?? '', |
|
|
|
proclamation: data.proclamation ?? data.fileList ?? [] |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
/** 将标准化后的数据写入响应式 formData */ |
|
|
|
const applyFormData = (data) => { |
|
|
|
const defaults = createDefaultFormData() |
|
|
|
const normalized = normalizeFormData(data) |
|
|
|
const defaults = createDefaultFormData(); |
|
|
|
const normalized = normalizeFormData(data); |
|
|
|
Object.assign(formData, defaults, normalized, { |
|
|
|
checkItemList: [...normalized.checkItemList], |
|
|
|
legalBasis: [...normalized.legalBasis], |
|
|
|
proclamation: serializeProclamation(normalized.proclamation) |
|
|
|
}) |
|
|
|
} |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
/** 重置表单、企业及执法人员等全部页面状态 */ |
|
|
|
const resetFormState = () => { |
|
|
|
applyFormData(createDefaultFormData()) |
|
|
|
formData.deadline = getDefaultEnforcementTime() |
|
|
|
enterpriseData.value = createDefaultEnterpriseData() |
|
|
|
additionalLawEnforcers.value = [] |
|
|
|
categoryDisabled.value = false |
|
|
|
} |
|
|
|
|
|
|
|
applyFormData(createDefaultFormData()); |
|
|
|
formData.deadline = getDefaultEnforcementTime(); |
|
|
|
enterpriseData.value = createDefaultEnterpriseData(); |
|
|
|
additionalLawEnforcers.value = []; |
|
|
|
categoryDisabled.value = false; |
|
|
|
}; |
|
|
|
|
|
|
|
/** 根据列表页带入的 tab 锁定任务类别并禁止修改 */ |
|
|
|
const applyTabCategoryFromRoute = () => { |
|
|
|
const taskTypeId = getTabTaskTypeId() |
|
|
|
const taskTypeId = getTabTaskTypeId(); |
|
|
|
|
|
|
|
if (taskTypeId !== null) { |
|
|
|
formData.taskTypeId = taskTypeId |
|
|
|
categoryDisabled.value = true |
|
|
|
formData.taskTypeId = taskTypeId; |
|
|
|
categoryDisabled.value = true; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** 将当前填写内容持久化到 sessionStorage 草稿 */ |
|
|
|
const saveDraftToStorage = (tab = getPageTabKey()) => { |
|
|
|
const draft = { |
|
|
|
formData: { |
|
|
|
@ -249,109 +263,119 @@ const saveDraftToStorage = (tab = getPageTabKey()) => { |
|
|
|
additionalLawEnforcers: JSON.parse(JSON.stringify(additionalLawEnforcers.value)), |
|
|
|
categoryDisabled: categoryDisabled.value, |
|
|
|
isSignMode: isSignMode.value |
|
|
|
} |
|
|
|
sessionStorage.setItem(getDraftStorageKey(tab), JSON.stringify(draft)) |
|
|
|
} |
|
|
|
}; |
|
|
|
sessionStorage.setItem(getDraftStorageKey(tab), JSON.stringify(draft)); |
|
|
|
}; |
|
|
|
|
|
|
|
/** 从 sessionStorage 读取指定 Tab 的草稿 */ |
|
|
|
const loadDraftFromStorage = (tab = getPageTabKey()) => { |
|
|
|
try { |
|
|
|
const raw = sessionStorage.getItem(getDraftStorageKey(tab)) |
|
|
|
return raw ? JSON.parse(raw) : null |
|
|
|
const raw = sessionStorage.getItem(getDraftStorageKey(tab)); |
|
|
|
return raw ? JSON.parse(raw) : null; |
|
|
|
} catch (e) { |
|
|
|
console.error("读取新增页草稿失败", e) |
|
|
|
return null |
|
|
|
console.error('读取新增页草稿失败', e); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** 清除指定 Tab 的本地草稿 */ |
|
|
|
const clearDraftFromStorage = (tab = getPageTabKey()) => { |
|
|
|
sessionStorage.removeItem(getDraftStorageKey(tab)) |
|
|
|
} |
|
|
|
sessionStorage.removeItem(getDraftStorageKey(tab)); |
|
|
|
}; |
|
|
|
|
|
|
|
/** 将草稿对象还原到页面各响应式状态 */ |
|
|
|
const restoreDraft = (draft) => { |
|
|
|
applyFormData(draft.formData) |
|
|
|
const draftEnterprise = draft.enterpriseData || {} |
|
|
|
applyFormData(draft.formData); |
|
|
|
const draftEnterprise = draft.enterpriseData || {}; |
|
|
|
enterpriseData.value = { |
|
|
|
enterpriseName: draftEnterprise.enterpriseName || "", |
|
|
|
usciCode: draftEnterprise.usciCode || draftEnterprise.enterpriseNumber || "", |
|
|
|
enterpriseId: draftEnterprise.enterpriseId || "" |
|
|
|
} |
|
|
|
lawEnforcer.value = draft.lawEnforcer || lawEnforcer.value |
|
|
|
additionalLawEnforcers.value = draft.additionalLawEnforcers || draft.additionalPersons || [] |
|
|
|
categoryDisabled.value = !!draft.categoryDisabled |
|
|
|
isSignMode.value = !!draft.isSignMode |
|
|
|
} |
|
|
|
|
|
|
|
enterpriseName: draftEnterprise.enterpriseName || '', |
|
|
|
usciCode: draftEnterprise.usciCode || draftEnterprise.enterpriseNumber || '', |
|
|
|
enterpriseId: draftEnterprise.enterpriseId || '' |
|
|
|
}; |
|
|
|
lawEnforcer.value = draft.lawEnforcer || lawEnforcer.value; |
|
|
|
additionalLawEnforcers.value = draft.additionalLawEnforcers || draft.additionalPersons || []; |
|
|
|
categoryDisabled.value = !!draft.categoryDisabled; |
|
|
|
isSignMode.value = !!draft.isSignMode; |
|
|
|
}; |
|
|
|
|
|
|
|
/** 非补录模式下,从扫码缓存恢复企业信息 */ |
|
|
|
const initEnterpriseFromCache = () => { |
|
|
|
if (isSignMode.value) return |
|
|
|
const cached = sessionStorage.getItem("enterpriseScanData") |
|
|
|
if (!cached) return |
|
|
|
if (isSignMode.value) return; |
|
|
|
const cached = sessionStorage.getItem('enterpriseScanData'); |
|
|
|
if (!cached) return; |
|
|
|
try { |
|
|
|
const parsed = JSON.parse(cached) |
|
|
|
const parsed = JSON.parse(cached); |
|
|
|
enterpriseData.value = { |
|
|
|
enterpriseName: parsed.enterpriseName || "", |
|
|
|
usciCode: parsed.usciCode || parsed.enterpriseNumber || "", |
|
|
|
enterpriseId: parsed.enterpriseId || "" |
|
|
|
} |
|
|
|
enterpriseName: parsed.enterpriseName || '', |
|
|
|
usciCode: parsed.usciCode || parsed.enterpriseNumber || '', |
|
|
|
enterpriseId: parsed.enterpriseId || '' |
|
|
|
}; |
|
|
|
} catch (e) { |
|
|
|
console.error("解析企业缓存数据失败", e) |
|
|
|
console.error('解析企业缓存数据失败', e); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* 页面进入时的初始化逻辑(keep-alive 场景) |
|
|
|
* - Tab 切换时先保存旧 Tab 草稿再重置 |
|
|
|
* - 优先恢复当前 Tab 草稿,否则应用路由类别并设置默认截止时间 |
|
|
|
*/ |
|
|
|
const handlePageEnter = () => { |
|
|
|
const tab = getPageTabKey() |
|
|
|
const tab = getPageTabKey(); |
|
|
|
|
|
|
|
if (lastActiveTab.value && lastActiveTab.value !== tab) { |
|
|
|
saveDraftToStorage(lastActiveTab.value) |
|
|
|
resetFormState() |
|
|
|
saveDraftToStorage(lastActiveTab.value); |
|
|
|
resetFormState(); |
|
|
|
} |
|
|
|
lastActiveTab.value = tab |
|
|
|
lastActiveTab.value = tab; |
|
|
|
|
|
|
|
const draft = loadDraftFromStorage(tab) |
|
|
|
const draft = loadDraftFromStorage(tab); |
|
|
|
if (draft) { |
|
|
|
restoreDraft(draft) |
|
|
|
return |
|
|
|
restoreDraft(draft); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
applyTabCategoryFromRoute() |
|
|
|
applyTabCategoryFromRoute(); |
|
|
|
if (!formData.deadline) { |
|
|
|
formData.deadline = getDefaultEnforcementTime() |
|
|
|
formData.deadline = getDefaultEnforcementTime(); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const taskSourceOptions = ref([]) |
|
|
|
const taskSourceOptions = ref([]); |
|
|
|
|
|
|
|
/** 拉取任务来源下拉选项 */ |
|
|
|
const fetchTaskSourceList = () => { |
|
|
|
nosTaskSourceListApi( |
|
|
|
{}, |
|
|
|
(res) => { |
|
|
|
if (res.code === 200) { |
|
|
|
const list = res.rows ?? res.data ?? [] |
|
|
|
const list = res.rows ?? res.data ?? []; |
|
|
|
taskSourceOptions.value = list.map((item) => ({ |
|
|
|
text: item.sourceName, |
|
|
|
value: item.id |
|
|
|
})) |
|
|
|
})); |
|
|
|
} |
|
|
|
}, |
|
|
|
(err) => { |
|
|
|
console.error("获取任务来源列表失败", err) |
|
|
|
console.error('获取任务来源列表失败', err); |
|
|
|
} |
|
|
|
) |
|
|
|
} |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
// ========== 事件处理函数 ========== |
|
|
|
|
|
|
|
// 关闭弹窗(保持 reactive 对象的响应式) |
|
|
|
/** 关闭指定类型的弹窗 */ |
|
|
|
const handleClosePopup = (type) => { |
|
|
|
showPopups[type] = false |
|
|
|
} |
|
|
|
showPopups[type] = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 打开人员选择器 |
|
|
|
/** 打开执法人员选择弹窗,index 为额外人员列表中的编辑下标 */ |
|
|
|
const handleOpenPersonPicker = (index) => { |
|
|
|
currentEditIndex.value = index |
|
|
|
showPopups.person = true |
|
|
|
} |
|
|
|
currentEditIndex.value = index; |
|
|
|
showPopups.person = true; |
|
|
|
}; |
|
|
|
|
|
|
|
// 选择人员 |
|
|
|
/** 确认选择执法人员:新增或替换 additionalLawEnforcers 中对应项 */ |
|
|
|
const handleSelectPerson = (person) => { |
|
|
|
if (currentEditIndex.value === -1) { |
|
|
|
additionalLawEnforcers.value.push({ |
|
|
|
@ -359,105 +383,105 @@ const handleSelectPerson = (person) => { |
|
|
|
lawEnforcerId: person.lawEnforcerId, |
|
|
|
lawEnforcerPhone: person.lawEnforcerPhone, |
|
|
|
lawEnforcerIdCard: person.lawEnforcerIdCard |
|
|
|
}) |
|
|
|
}); |
|
|
|
} else { |
|
|
|
additionalLawEnforcers.value[currentEditIndex.value] = { |
|
|
|
lawEnforcerName: person.lawEnforcerName, |
|
|
|
lawEnforcerId: person.lawEnforcerId, |
|
|
|
lawEnforcerPhone: person.lawEnforcerPhone, |
|
|
|
lawEnforcerIdCard: person.lawEnforcerIdCard |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
showPopups.person = false |
|
|
|
} |
|
|
|
showPopups.person = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 删除额外人员 |
|
|
|
/** 删除指定下标的额外执法人员 */ |
|
|
|
const handleRemovePerson = (index) => { |
|
|
|
additionalLawEnforcers.value.splice(index, 1) |
|
|
|
} |
|
|
|
additionalLawEnforcers.value.splice(index, 1); |
|
|
|
}; |
|
|
|
|
|
|
|
// 添加额外人员 |
|
|
|
/** 在额外执法人员列表末尾追加空行 */ |
|
|
|
const handleAddPerson = () => { |
|
|
|
additionalLawEnforcers.value.push({}) |
|
|
|
} |
|
|
|
additionalLawEnforcers.value.push({}); |
|
|
|
}; |
|
|
|
|
|
|
|
// 打开执法依据选择器 |
|
|
|
/** 打开执法依据选择弹窗,index 为 legalBasis 中的编辑下标 */ |
|
|
|
const handleOpenBasisPicker = (index) => { |
|
|
|
currentEditIndex.value = index |
|
|
|
showPopups.basis = true |
|
|
|
} |
|
|
|
currentEditIndex.value = index; |
|
|
|
showPopups.basis = true; |
|
|
|
}; |
|
|
|
|
|
|
|
// 添加执法依据 |
|
|
|
/** 在执法依据列表末尾追加空项 */ |
|
|
|
const handleAddBasis = () => { |
|
|
|
formData.legalBasis.push("") |
|
|
|
} |
|
|
|
formData.legalBasis.push(''); |
|
|
|
}; |
|
|
|
|
|
|
|
// 删除执法依据 |
|
|
|
/** 删除指定下标的执法依据(至少保留一项) */ |
|
|
|
const handleRemoveBasis = (index) => { |
|
|
|
if (formData.legalBasis.length > 1) { |
|
|
|
formData.legalBasis.splice(index, 1) |
|
|
|
formData.legalBasis.splice(index, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 选择执法依据 |
|
|
|
/** 将选中的执法依据写入 legalBasis 对应下标 */ |
|
|
|
const handleSelectBasis = (basis) => { |
|
|
|
const index = currentEditIndex.value |
|
|
|
const index = currentEditIndex.value; |
|
|
|
if (index >= 0 && index < formData.legalBasis.length) { |
|
|
|
formData.legalBasis[index] = basis.name |
|
|
|
formData.legalBasis[index] = basis.name; |
|
|
|
} |
|
|
|
showPopups.basis = false |
|
|
|
} |
|
|
|
showPopups.basis = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 选择截止时间(格式:YYYY-MM-DD) |
|
|
|
/** 确认选择任务截止时间(格式:YYYY-MM-DD) */ |
|
|
|
const handleSelectTime = (time) => { |
|
|
|
formData.deadline = time |
|
|
|
showPopups.time = false |
|
|
|
} |
|
|
|
formData.deadline = time; |
|
|
|
showPopups.time = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 选择企业 |
|
|
|
/** 确认选择检查对象企业并回填 enterpriseData */ |
|
|
|
const handleSelectEnterprise = (enterprise) => { |
|
|
|
enterpriseData.value = { |
|
|
|
enterpriseName: enterprise.enterpriseName, |
|
|
|
usciCode: enterprise.usciCode, |
|
|
|
enterpriseId: enterprise.enterpriseId |
|
|
|
} |
|
|
|
showPopups.enterprise = false |
|
|
|
} |
|
|
|
}; |
|
|
|
showPopups.enterprise = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 类别选择确认 |
|
|
|
/** 确认选择任务类别(taskTypeId) */ |
|
|
|
const handleCategoryConfirm = ({ selectedOptions }) => { |
|
|
|
formData.taskTypeId = selectedOptions[0]?.value ?? null |
|
|
|
showPopups.category = false |
|
|
|
} |
|
|
|
formData.taskTypeId = selectedOptions[0]?.value ?? null; |
|
|
|
showPopups.category = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 任务来源选择确认 |
|
|
|
/** 确认选择任务来源(taskSourceId) */ |
|
|
|
const handleTaskSourceConfirm = ({ selectedOptions }) => { |
|
|
|
formData.taskSourceId = selectedOptions[0]?.value || "" |
|
|
|
showPopups.taskSource = false |
|
|
|
} |
|
|
|
formData.taskSourceId = selectedOptions[0]?.value || ''; |
|
|
|
showPopups.taskSource = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 返回上一页(保留草稿,在 onDeactivated 中持久化) |
|
|
|
/** 返回上一页(草稿在 onDeactivated 中自动保存) */ |
|
|
|
const goBack = () => { |
|
|
|
router.back() |
|
|
|
} |
|
|
|
router.back(); |
|
|
|
}; |
|
|
|
|
|
|
|
// 重置表单并清除当前 Tab 草稿 |
|
|
|
/** 二次确认后重置表单并清除当前 Tab 草稿 */ |
|
|
|
const handleReset = () => { |
|
|
|
showConfirmDialog({ |
|
|
|
title: "确认重置", |
|
|
|
message: "重置后将清空已填写内容和附件,是否继续?", |
|
|
|
width: "80%" |
|
|
|
title: '确认重置', |
|
|
|
message: '重置后将清空已填写内容和附件,是否继续?', |
|
|
|
width: '80%' |
|
|
|
}) |
|
|
|
.then(() => { |
|
|
|
clearDraftFromStorage() |
|
|
|
resetFormState() |
|
|
|
applyTabCategoryFromRoute() |
|
|
|
showSuccessToast("已重置") |
|
|
|
clearDraftFromStorage(); |
|
|
|
resetFormState(); |
|
|
|
applyTabCategoryFromRoute(); |
|
|
|
showSuccessToast('已重置'); |
|
|
|
}) |
|
|
|
.catch(() => {}) |
|
|
|
} |
|
|
|
.catch(() => {}); |
|
|
|
}; |
|
|
|
|
|
|
|
// 组装执法人员列表 |
|
|
|
/** 合并主执法人员与额外人员,过滤空项后返回提交结构 */ |
|
|
|
const buildLawEnforcerList = () => { |
|
|
|
const list = [...lawEnforcer.value, ...additionalLawEnforcers.value] |
|
|
|
.filter((item) => item?.lawEnforcerName) |
|
|
|
@ -466,20 +490,20 @@ const buildLawEnforcerList = () => { |
|
|
|
lawEnforcerName: item.lawEnforcerName, |
|
|
|
lawEnforcerPhone: item.lawEnforcerPhone, |
|
|
|
lawEnforcerIdCard: item.lawEnforcerIdCard |
|
|
|
})) |
|
|
|
return list |
|
|
|
} |
|
|
|
})); |
|
|
|
return list; |
|
|
|
}; |
|
|
|
|
|
|
|
// 将上传附件转换为 proclamation |
|
|
|
/** 将 uploader 附件列表转换为接口所需的 proclamation 结构 */ |
|
|
|
const buildProclamation = () => |
|
|
|
(formData.proclamation || []) |
|
|
|
.filter((file) => file && file.url) |
|
|
|
.map((file) => ({ |
|
|
|
fileName: file.name || file.file?.name || "", |
|
|
|
fileName: file.name || file.file?.name || '', |
|
|
|
filePath: toRelativeFilePath(file.url) |
|
|
|
})) |
|
|
|
})); |
|
|
|
|
|
|
|
// 构建提交参数(NosLawEnforcementTaskSaveBO) |
|
|
|
/** 组装新增任务接口入参(NosLawEnforcementTaskSaveBO) */ |
|
|
|
const buildSubmitPayload = () => ({ |
|
|
|
checkItemList: formData.checkItemList.filter((item) => item?.trim()), |
|
|
|
deadline: formData.deadline, |
|
|
|
@ -493,81 +517,85 @@ const buildSubmitPayload = () => ({ |
|
|
|
taskSourceId: formData.taskSourceId, |
|
|
|
taskTypeId: formData.taskTypeId, |
|
|
|
usciCode: enterpriseData.value.usciCode |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
// 取消 |
|
|
|
/** 二次确认后清空草稿、重置表单并返回列表 */ |
|
|
|
const handleCancel = () => { |
|
|
|
showConfirmDialog({ |
|
|
|
title: "确认取消", |
|
|
|
message: "取消后将清空已填写内容,是否继续?", |
|
|
|
width: "80%" |
|
|
|
title: '确认取消', |
|
|
|
message: '取消后将清空已填写内容,是否继续?', |
|
|
|
width: '80%' |
|
|
|
}) |
|
|
|
.then(() => { |
|
|
|
clearDraftFromStorage() |
|
|
|
resetFormState() |
|
|
|
applyTabCategoryFromRoute() |
|
|
|
router.back() |
|
|
|
clearDraftFromStorage(); |
|
|
|
resetFormState(); |
|
|
|
applyTabCategoryFromRoute(); |
|
|
|
router.back(); |
|
|
|
}) |
|
|
|
.catch(() => {}) |
|
|
|
} |
|
|
|
.catch(() => {}); |
|
|
|
}; |
|
|
|
|
|
|
|
// 提交表单 |
|
|
|
/** 校验附件上传状态后,二次确认并调用新增任务接口 */ |
|
|
|
const onSubmit = () => { |
|
|
|
// 有未上传完的附件则拦截 |
|
|
|
const uploadingFile = (formData.proclamation || []).find((img) => img && img.status === "uploading") |
|
|
|
const uploadingFile = (formData.proclamation || []).find((img) => img && img.status === 'uploading'); |
|
|
|
if (uploadingFile) { |
|
|
|
showToast("附件上传中,请稍后") |
|
|
|
return |
|
|
|
showToast('附件上传中,请稍后'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
showConfirmDialog({ |
|
|
|
title: "确认提交", |
|
|
|
message: "确认提交吗?提交后将无法修改。", |
|
|
|
width: "80%" |
|
|
|
title: '确认提交', |
|
|
|
message: '确认提交吗?提交后将无法修改。', |
|
|
|
width: '80%' |
|
|
|
}) |
|
|
|
.then(() => { |
|
|
|
const payload = buildSubmitPayload() |
|
|
|
console.log("提交数据:", payload) |
|
|
|
const payload = buildSubmitPayload(); |
|
|
|
console.log('提交数据:', payload); |
|
|
|
nosAddApi( |
|
|
|
payload, |
|
|
|
(res) => { |
|
|
|
console.log(res) |
|
|
|
clearDraftFromStorage() |
|
|
|
resetFormState() |
|
|
|
applyTabCategoryFromRoute() |
|
|
|
showSuccessToast("提交成功") |
|
|
|
clearDraftFromStorage(); |
|
|
|
resetFormState(); |
|
|
|
applyTabCategoryFromRoute(); |
|
|
|
showSuccessToast('提交成功'); |
|
|
|
setTimeout(() => { |
|
|
|
router.back() |
|
|
|
}, 500) |
|
|
|
router.back(); |
|
|
|
}, 500); |
|
|
|
}, |
|
|
|
(err) => { |
|
|
|
console.log(err) |
|
|
|
console.log(err); |
|
|
|
showToast(err?.message || '提交失败'); |
|
|
|
} |
|
|
|
) |
|
|
|
); |
|
|
|
}) |
|
|
|
.catch(() => { |
|
|
|
// 用户取消 |
|
|
|
}) |
|
|
|
} |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
// ========== 生命周期(keep-alive:onMounted 仅一次,onActivated 每次进入) ========== |
|
|
|
|
|
|
|
/** 首次挂载:恢复扫码企业缓存并加载任务来源 */ |
|
|
|
onMounted(() => { |
|
|
|
initEnterpriseFromCache() |
|
|
|
fetchTaskSourceList() |
|
|
|
}) |
|
|
|
initEnterpriseFromCache(); |
|
|
|
fetchTaskSourceList(); |
|
|
|
}); |
|
|
|
|
|
|
|
/** 每次从缓存激活:恢复或初始化当前 Tab 表单 */ |
|
|
|
onActivated(() => { |
|
|
|
handlePageEnter() |
|
|
|
}) |
|
|
|
handlePageEnter(); |
|
|
|
}); |
|
|
|
|
|
|
|
/** 离开页面时自动保存当前 Tab 草稿 */ |
|
|
|
onDeactivated(() => { |
|
|
|
saveDraftToStorage(lastActiveTab.value || getPageTabKey()) |
|
|
|
}) |
|
|
|
saveDraftToStorage(lastActiveTab.value || getPageTabKey()); |
|
|
|
}); |
|
|
|
|
|
|
|
// 路由 push 到本页时触发(与项目 keep-alive 约定一致) |
|
|
|
/** 路由 push 到本页时触发(与项目 keep-alive 约定一致) */ |
|
|
|
$globalConfigure(() => { |
|
|
|
handlePageEnter() |
|
|
|
}) |
|
|
|
handlePageEnter(); |
|
|
|
}); |
|
|
|
</script> |
|
|
|
|
|
|
|
<style lang="less" scoped> |
|
|
|
|