refactor(aireport): 重构报告任务模块数据结构和界面组件
- 扩展 ReportTaskGenerateState 类型定义,增加状态值 3 和 4 - 移除 ReportTaskRecord 中的 clientUnitId、clientUnitName、createUnit、contractNumber、standard、phonenumber 字段 - 新增 multiId、templateDirName、templateDirPath、sortNo 等字段到 ReportTaskRecord - 更新 ReportTaskAddParam 接口,移除 clientUnitId、createUnit、contractNumber、standard、phonenumber 参数 - 在 PointGroupItem 和 GroupReportRecord 中增加 reportNo、clientUnitId、createUnit、contractNumber、standard、phonenumber 字段 - 移除委托单位和检测公司等字段的显示列和表单验证规则 - 更新基础信息步骤组件,简化表单字段配置 - 调整详情对话框布局,增加分组报告表格中的委托单位、检测公司等列 - 优化分组数据显示逻辑,支持从快照数据获取分组数量 - 更新多报告界面组件,同步调整相关属性传递和数据加载逻辑
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
export namespace ReportTask {
|
||||
export type ReportTaskState = '01' | '02' | '03' | '04' | '05'
|
||||
export type ReportTaskGenerateState = 0 | 1 | 2
|
||||
export type ReportTaskGenerateState = 0 | 1 | 2 | 3 | 4
|
||||
export type ReportTaskGroupReportGenerateState = 0 | 1 | 2 | 3
|
||||
export type ReportTaskLedgerImportStage =
|
||||
| '选择文件'
|
||||
@@ -12,16 +12,14 @@ export namespace ReportTask {
|
||||
|
||||
export interface ReportTaskRecord {
|
||||
id?: string
|
||||
multiId?: string | null
|
||||
no?: string | null
|
||||
clientUnitId?: string | null
|
||||
clientUnitName?: string | null
|
||||
reportModelId?: string | null
|
||||
reportModelName?: string | null
|
||||
createUnit?: string | null
|
||||
contractNumber?: string | null
|
||||
standard?: string[] | string | null
|
||||
data?: string | null
|
||||
phonenumber?: string | null
|
||||
templateDirName?: string | null
|
||||
templateDirPath?: string | null
|
||||
sortNo?: number | null
|
||||
data?: Record<string, unknown> | unknown[] | string | null
|
||||
checkId?: string | null
|
||||
checkerName?: string | null
|
||||
checkTime?: string | null
|
||||
@@ -53,14 +51,9 @@ export namespace ReportTask {
|
||||
export interface ReportTaskAddParam {
|
||||
id?: string
|
||||
no: string
|
||||
clientUnitId: string
|
||||
reportModelId: string
|
||||
createUnit: string
|
||||
contractNumber: string
|
||||
standard: string[]
|
||||
data: Record<string, unknown> | unknown[]
|
||||
batchId?: string
|
||||
phonenumber?: string
|
||||
}
|
||||
|
||||
export interface ReportTaskSaveRequest extends ReportTaskAddParam {}
|
||||
@@ -181,11 +174,18 @@ export namespace ReportTask {
|
||||
protocolCapacity?: string | null
|
||||
powerSupplyCapacity?: string | null
|
||||
excelAttachmentName?: string | null
|
||||
wordAttachmentName?: string | null
|
||||
}
|
||||
|
||||
export interface ReportTaskPointGroupItem {
|
||||
groupNo: number
|
||||
pointIds: string[]
|
||||
reportNo?: string
|
||||
clientUnitId?: string
|
||||
createUnit?: string
|
||||
contractNumber?: string
|
||||
standard?: string[]
|
||||
phonenumber?: string
|
||||
}
|
||||
|
||||
export interface ReportTaskGroupSaveRequest {
|
||||
@@ -195,6 +195,12 @@ export namespace ReportTask {
|
||||
export interface ReportTaskGroupReportRecord {
|
||||
id?: string
|
||||
groupNo?: number | null
|
||||
reportNo?: string | null
|
||||
clientUnitId?: string | null
|
||||
createUnit?: string | null
|
||||
contractNumber?: string | null
|
||||
standard?: string[] | string | null
|
||||
phonenumber?: string | null
|
||||
reportName?: string | null
|
||||
reportFileName?: string | null
|
||||
reportStoragePath?: string | null
|
||||
|
||||
@@ -56,12 +56,7 @@ export namespace ReportTaskMulti {
|
||||
templateDirName: string
|
||||
templateDirPath: string
|
||||
no: string
|
||||
clientUnitId: string
|
||||
reportModelId: string
|
||||
createUnit: string
|
||||
contractNumber: string
|
||||
standard: string[]
|
||||
phonenumber?: string
|
||||
}
|
||||
|
||||
export interface ReportTaskMultiCreateParam {
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
<template>
|
||||
<div class="form-panel">
|
||||
<el-form ref="formRef" :model="formModel" :rules="formRules" label-width="108px" class="report-task-form">
|
||||
<el-form ref="formRef" :model="localFormModel" :rules="formRules" label-width="108px" class="report-task-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="报告编号" prop="no">
|
||||
<el-input v-model="localFormModel.no" maxlength="32" clearable placeholder="请输入报告编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="委托单位" prop="clientUnitId">
|
||||
<el-select v-model="localFormModel.clientUnitId" filterable clearable placeholder="请选择委托单位">
|
||||
<el-option v-for="option in clientUnitSelectOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="报告模板" prop="reportModelId">
|
||||
<el-select v-model="localFormModel.reportModelId" filterable clearable placeholder="请选择报告模板">
|
||||
@@ -21,61 +14,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="检测公司" prop="createUnit">
|
||||
<el-select v-model="localFormModel.createUnit" filterable clearable placeholder="请选择检测公司">
|
||||
<el-option v-for="option in companySelectOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="合同编号" prop="contractNumber">
|
||||
<el-input v-model="localFormModel.contractNumber" maxlength="32" clearable placeholder="请输入合同编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="测试依据" prop="standardIds">
|
||||
<el-select v-model="localFormModel.standardIds" multiple filterable clearable collapse-tags placeholder="请选择测试依据">
|
||||
<el-option v-for="option in standardSelectOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="联系电话" prop="phonenumber">
|
||||
<el-input v-model="localFormModel.phonenumber" maxlength="32" clearable placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="summary-strip">
|
||||
<div class="summary-item">
|
||||
<span class="summary-label">导入状态</span>
|
||||
<el-tag :type="canSubmit ? 'success' : 'warning'">
|
||||
{{ canSubmit ? '已准备提交' : '待完成正式导入' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<span class="summary-label">监测点数</span>
|
||||
<span class="summary-value">{{ importSummary.pointCount }}</span>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<span class="summary-label">分组数</span>
|
||||
<span class="summary-value">{{ importSummary.groupCount }}</span>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<span class="summary-label">汇总文件</span>
|
||||
<span class="summary-value">{{ importSummary.summaryFileName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { computed, reactive, ref, watch } from 'vue'
|
||||
import type { ReportTask } from '@/api/aireport/testReport/interface'
|
||||
import { checkReportTaskLedgerPrepared } from '../utils/testReport'
|
||||
import type { ReportTaskFormModel } from '../utils/testReportForm'
|
||||
|
||||
defineOptions({
|
||||
@@ -85,28 +32,19 @@ defineOptions({
|
||||
const props = defineProps<{
|
||||
formModel: ReportTaskFormModel
|
||||
record: ReportTask.ReportTaskRecord | null
|
||||
clientUnitOptions: Array<{ label: string; value: string }>
|
||||
reportModelOptions: Array<{ label: string; value: string }>
|
||||
companyOptions: Array<{ label: string; value: string }>
|
||||
standardOptions: Array<{ label: string; value: string }>
|
||||
preparedState: ReportTask.ReportTaskLedgerPreparedState
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'register-form', value: FormInstance | undefined): void
|
||||
(event: 'update:form-model', value: ReportTaskFormModel): void
|
||||
}>()
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const localFormModel = reactive<ReportTaskFormModel>({ ...props.formModel })
|
||||
const localFormModel = ref<ReportTaskFormModel>({ ...props.formModel })
|
||||
|
||||
const formRules: FormRules = {
|
||||
no: [{ required: true, message: '请输入报告编号', trigger: 'blur' }],
|
||||
clientUnitId: [{ required: true, message: '请选择委托单位', trigger: 'change' }],
|
||||
reportModelId: [{ required: true, message: '请选择报告模板', trigger: 'change' }],
|
||||
createUnit: [{ required: true, message: '请选择检测公司', trigger: 'change' }],
|
||||
contractNumber: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
|
||||
standardIds: [{ required: true, message: '请选择测试依据', trigger: 'change' }]
|
||||
reportModelId: [{ required: true, message: '请选择报告模板', trigger: 'change' }]
|
||||
}
|
||||
|
||||
const ensureCurrentOption = (
|
||||
@@ -118,56 +56,29 @@ const ensureCurrentOption = (
|
||||
return [...options, { label: fallbackLabel || value, value }]
|
||||
}
|
||||
|
||||
const clientUnitSelectOptions = computed(() =>
|
||||
ensureCurrentOption(props.clientUnitOptions, localFormModel.clientUnitId, props.record?.clientUnitName || '')
|
||||
)
|
||||
const reportModelSelectOptions = computed(() =>
|
||||
ensureCurrentOption(props.reportModelOptions, localFormModel.reportModelId, props.record?.reportModelName || '')
|
||||
)
|
||||
const companySelectOptions = computed(() =>
|
||||
ensureCurrentOption(props.companyOptions, localFormModel.createUnit, props.record?.createUnit || '')
|
||||
)
|
||||
const standardSelectOptions = computed(() => {
|
||||
const optionMap = new Map(props.standardOptions.map(option => [option.value, option]))
|
||||
const extraOptions = localFormModel.standardIds.filter(item => !optionMap.has(item)).map(item => ({ label: item, value: item }))
|
||||
return [...props.standardOptions, ...extraOptions]
|
||||
})
|
||||
|
||||
const canSubmit = computed(() => checkReportTaskLedgerPrepared(props.preparedState))
|
||||
const importSummary = computed(() => {
|
||||
const importResult = props.preparedState.latestImportResult
|
||||
const snapshot = props.preparedState.snapshot
|
||||
|
||||
return {
|
||||
pointCount: String(importResult?.pointCount ?? snapshot?.rowCount ?? '-'),
|
||||
groupCount: String(importResult?.groupCount ?? snapshot?.groupSummary?.length ?? '-'),
|
||||
summaryFileName: importResult?.summaryFileName || snapshot?.summaryFileName || '-'
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
formRef,
|
||||
value => {
|
||||
emit('register-form', value)
|
||||
},
|
||||
{ immediate: true }
|
||||
ensureCurrentOption(props.reportModelOptions, localFormModel.value.reportModelId, props.record?.reportModelName || '')
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.formModel,
|
||||
value => {
|
||||
Object.assign(localFormModel, value)
|
||||
localFormModel.value = { ...value }
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => localFormModel.value,
|
||||
value => {
|
||||
emit('update:form-model', { ...value })
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
localFormModel,
|
||||
value => {
|
||||
emit('update:form-model', { ...value, standardIds: [...value.standardIds] })
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
defineExpose({
|
||||
validate: () => formRef.value?.validate()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -178,44 +89,8 @@ watch(
|
||||
background: var(--el-fill-color-blank);
|
||||
}
|
||||
|
||||
.summary-strip {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
padding: 12px 14px;
|
||||
border-radius: 10px;
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
.summary-value {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
:deep(.report-task-form .el-form-item) {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
:deep(.el-select),
|
||||
:deep(.el-input) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.summary-strip {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
<el-result
|
||||
icon="success"
|
||||
:title="mode === 'create' ? '报告任务新增完成' : '报告任务编辑完成'"
|
||||
sub-title="文件导入与基础信息保存均已完成,本次结果已同步刷新到列表。"
|
||||
sub-title="文件导入与任务基础信息保存均已完成。"
|
||||
/>
|
||||
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="报告编号">{{ formModel.no || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="委托单位">{{ resolveCurrentOptionLabel(clientUnitOptions, formModel.clientUnitId) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="检测公司">{{ resolveCurrentOptionLabel(companyOptions, formModel.createUnit) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报告模板">{{ resolveCurrentOptionLabel(reportModelOptions, formModel.reportModelId) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="监测点数">{{ importSummary.pointCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分组数">{{ importSummary.groupCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="汇总文件">{{ importSummary.summaryFileName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="汇总文件" :span="2">{{ importSummary.summaryFileName }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
@@ -29,8 +28,7 @@ const props = defineProps<{
|
||||
mode: 'create' | 'edit'
|
||||
formModel: ReportTaskFormModel
|
||||
preparedState: ReportTask.ReportTaskLedgerPreparedState
|
||||
clientUnitOptions: Array<{ label: string; value: string }>
|
||||
companyOptions: Array<{ label: string; value: string }>
|
||||
reportModelOptions: Array<{ label: string; value: string }>
|
||||
}>()
|
||||
|
||||
const resolveCurrentOptionLabel = (options: Array<{ label: string; value: string }>, value: string) =>
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
<template>
|
||||
<el-dialog v-model="visibleProxy" title="报告任务详情" width="880px" append-to-body destroy-on-close>
|
||||
<el-dialog v-model="visibleProxy" title="报告任务详情" width="1200px" append-to-body destroy-on-close>
|
||||
<div v-loading="loading" class="report-task-detail-dialog">
|
||||
<el-descriptions class="detail-descriptions" :column="2" border>
|
||||
<el-descriptions-item label="报告编号">{{ resolveReportTaskText(detail?.no) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="委托单位">{{ resolveReportTaskText(detail?.clientUnitName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报告模板">{{ resolveReportTaskText(detail?.reportModelName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="检测公司">
|
||||
{{ resolveReportTaskCreateUnitText(detail?.createUnit, companyLabelMap) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合同编号">{{ resolveReportTaskText(detail?.contractNumber) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ resolveReportTaskText(detail?.phonenumber) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="测试依据" :span="2">
|
||||
{{ resolveReportTaskStandardText(detail?.standard, standardLabelMap) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="送资数据" :span="2">{{ resolveReportTaskText(detail?.data) }}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="模板目录">{{ resolveReportTaskText(detail?.templateDirName) }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="导入汇总快照数据" :span="2">{{ resolveReportTaskText(detail?.data) }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="监测点数量">{{ resolveReportTaskText(detail?.pointCount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分组数量">{{ resolveReportTaskText(detail?.groupCount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分组数量">{{ resolveReportTaskText(displayGroupCount) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核人">{{ resolveReportTaskText(detail?.checkerName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">{{ resolveReportTaskText(detail?.checkTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见" :span="2">{{ resolveReportTaskText(detail?.checkResult) }}</el-descriptions-item>
|
||||
@@ -30,10 +22,28 @@
|
||||
</el-descriptions>
|
||||
|
||||
<div class="group-report-section">
|
||||
<div class="group-report-title">分组报告生成状态</div>
|
||||
<div class="group-report-title">分组报告</div>
|
||||
<el-empty v-if="!groupReports.length" description="暂无分组报告记录" :image-size="88" />
|
||||
<el-table v-else :data="groupReports" border size="small">
|
||||
<el-table-column prop="groupNo" label="分组号" width="100" />
|
||||
<el-table-column prop="groupNo" label="分组号" width="90" />
|
||||
<el-table-column prop="reportNo" label="报告编号" min-width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ resolveReportTaskText(row.reportNo) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="委托单位" min-width="180" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ resolveReportTaskClientUnitText(row.clientUnitId, clientUnitLabelMap) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检测公司" min-width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ resolveReportTaskCreateUnitText(row.createUnit, companyLabelMap) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="contractNumber" label="合同编号" min-width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ resolveReportTaskText(row.contractNumber) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检测依据" min-width="220" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ resolveReportTaskStandardText(row.standard, standardLabelMap) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="phonenumber" label="联系电话" min-width="140" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ resolveReportTaskText(row.phonenumber) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="reportName" label="报告名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="生成状态" width="120">
|
||||
<template #default="{ row }">
|
||||
@@ -70,6 +80,7 @@
|
||||
import { computed } from 'vue'
|
||||
import type { ReportTask } from '@/api/aireport/testReport/interface'
|
||||
import {
|
||||
normalizeReportTaskLedgerSnapshot,
|
||||
resolveReportTaskCreateUnitText,
|
||||
resolveReportTaskGroupReportGenerateStateTagType,
|
||||
resolveReportTaskGroupReportGenerateStateText,
|
||||
@@ -86,6 +97,7 @@ const props = defineProps<{
|
||||
loading: boolean
|
||||
detail: ReportTask.ReportTaskRecord | null
|
||||
groupReports: ReportTask.ReportTaskGroupReportRecord[]
|
||||
clientUnitLabelMap: Record<string, string>
|
||||
companyLabelMap: Record<string, string>
|
||||
standardLabelMap: Record<string, string>
|
||||
downloadingGroupReportId?: string | null
|
||||
@@ -101,10 +113,28 @@ const visibleProxy = computed({
|
||||
set: value => emit('update:visible', value)
|
||||
})
|
||||
|
||||
const clientUnitLabelMap = computed(() => props.clientUnitLabelMap)
|
||||
const companyLabelMap = computed(() => props.companyLabelMap)
|
||||
const standardLabelMap = computed(() => props.standardLabelMap)
|
||||
const groupReports = computed(() => props.groupReports || [])
|
||||
const downloadingGroupReportId = computed(() => props.downloadingGroupReportId || '')
|
||||
const detailSnapshot = computed(() => normalizeReportTaskLedgerSnapshot(props.detail?.data as string | null | undefined))
|
||||
const displayGroupCount = computed(() => {
|
||||
if (groupReports.value.length > 0) {
|
||||
return groupReports.value.length
|
||||
}
|
||||
const snapshotGroupCount = Number(detailSnapshot.value?.groupSummary?.length ?? 0)
|
||||
if (Number.isInteger(snapshotGroupCount) && snapshotGroupCount > 0) {
|
||||
return snapshotGroupCount
|
||||
}
|
||||
return props.detail?.groupCount
|
||||
})
|
||||
|
||||
const resolveReportTaskClientUnitText = (value: string | null | undefined, labelMap: Record<string, string>) => {
|
||||
const text = String(value || '').trim()
|
||||
if (!text) return '-'
|
||||
return labelMap[text] || text
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -51,29 +51,7 @@
|
||||
<el-row :gutter="16">
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="报告编号" prop="no">
|
||||
<el-input
|
||||
v-model="formModel.no"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入报告编号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="委托单位" prop="clientUnitId">
|
||||
<el-select
|
||||
v-model="formModel.clientUnitId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择委托单位"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in clientUnitSelectOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-model="formModel.no" maxlength="32" clearable placeholder="请输入报告编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
@@ -93,62 +71,6 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="检测公司" prop="createUnit">
|
||||
<el-select
|
||||
v-model="formModel.createUnit"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择检测公司"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in companySelectOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="合同编号" prop="contractNumber">
|
||||
<el-input
|
||||
v-model="formModel.contractNumber"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入合同编号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="测试依据" prop="standardIds">
|
||||
<el-select
|
||||
v-model="formModel.standardIds"
|
||||
multiple
|
||||
filterable
|
||||
clearable
|
||||
collapse-tags
|
||||
placeholder="请选择测试依据"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in standardSelectOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="联系电话" prop="phonenumber">
|
||||
<el-input
|
||||
v-model="formModel.phonenumber"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入联系电话"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
@@ -180,20 +102,17 @@
|
||||
<el-result
|
||||
icon="success"
|
||||
:title="mode === 'create' ? '报告任务新增完成' : '报告任务编辑完成'"
|
||||
sub-title="台账校验与基础信息保存均已完成,本次结果已同步刷新到列表。"
|
||||
sub-title="台账校验与任务基础信息保存均已完成。"
|
||||
/>
|
||||
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="报告编号">{{ formModel.no || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="委托单位">
|
||||
{{ resolveCurrentOptionLabel(clientUnitSelectOptions, formModel.clientUnitId) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="检测公司">
|
||||
{{ resolveCurrentOptionLabel(companySelectOptions, formModel.createUnit) }}
|
||||
<el-descriptions-item label="报告模板">
|
||||
{{ resolveCurrentOptionLabel(reportModelSelectOptions, formModel.reportModelId) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="监测点数">{{ importSummary.pointCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分组数">{{ importSummary.groupCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="汇总文件">
|
||||
<el-descriptions-item label="汇总文件" :span="2">
|
||||
{{ importSummary.summaryFileName }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -203,11 +122,7 @@
|
||||
|
||||
<div class="log-panel" :class="{ 'is-collapsed': !logPanelExpanded }">
|
||||
<button type="button" class="log-panel-header" @click="logPanelExpanded = !logPanelExpanded">
|
||||
<span
|
||||
class="log-panel-toggle"
|
||||
:class="{ 'is-collapsed': !logPanelExpanded }"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<span class="log-panel-toggle" :class="{ 'is-collapsed': !logPanelExpanded }" aria-hidden="true"></span>
|
||||
<div class="log-title">日志信息</div>
|
||||
</button>
|
||||
|
||||
@@ -253,15 +168,7 @@ import { computed, reactive, ref, watch } from 'vue'
|
||||
import type { ReportTask } from '@/api/aireport/testReport/interface'
|
||||
import { generateUUID } from '@/utils'
|
||||
import ReportTaskLedgerImportPanel from './ReportTaskLedgerImportPanel.vue'
|
||||
import {
|
||||
checkReportTaskLedgerPrepared,
|
||||
getReportTaskErrorMessage,
|
||||
normalizeReportTaskLedgerSnapshot,
|
||||
normalizeReportTaskSelectedOptionValues,
|
||||
parseReportTaskStandardIds,
|
||||
resolveReportTaskOptionValue,
|
||||
stringifyReportTaskStandardIds
|
||||
} from '../utils/testReport'
|
||||
import { checkReportTaskLedgerPrepared, getReportTaskErrorMessage, normalizeReportTaskLedgerSnapshot } from '../utils/testReport'
|
||||
|
||||
defineOptions({
|
||||
name: 'ReportTaskFormDialog'
|
||||
@@ -276,24 +183,9 @@ const REPORT_TASK_FORM_STEPS: Array<{
|
||||
title: string
|
||||
description: string
|
||||
}> = [
|
||||
{
|
||||
index: 1,
|
||||
value: 'import',
|
||||
title: '数据导入',
|
||||
description: '先完成台账与附件校验'
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
value: 'form',
|
||||
title: '基础信息填写',
|
||||
description: '填写并确认任务基础信息'
|
||||
},
|
||||
{
|
||||
index: 3,
|
||||
value: 'done',
|
||||
title: '完成',
|
||||
description: '查看结果并结束本次流程'
|
||||
}
|
||||
{ index: 1, value: 'import', title: '数据导入', description: '先完成台账与附件校验' },
|
||||
{ index: 2, value: 'form', title: '任务信息', description: '填写任务编号和报告模板' },
|
||||
{ index: 3, value: 'done', title: '完成', description: '查看结果并结束本次流程' }
|
||||
]
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -335,22 +227,13 @@ const lastHandledSaveSuccessVersion = ref(0)
|
||||
const formModel = reactive({
|
||||
id: '',
|
||||
no: '',
|
||||
clientUnitId: '',
|
||||
reportModelId: '',
|
||||
createUnit: '',
|
||||
contractNumber: '',
|
||||
standardIds: [] as string[],
|
||||
data: '{}',
|
||||
phonenumber: ''
|
||||
data: '{}'
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
no: [{ required: true, message: '请输入报告编号', trigger: 'blur' }],
|
||||
clientUnitId: [{ required: true, message: '请选择委托单位', trigger: 'change' }],
|
||||
reportModelId: [{ required: true, message: '请选择报告模板', trigger: 'change' }],
|
||||
createUnit: [{ required: true, message: '请选择检测公司', trigger: 'change' }],
|
||||
contractNumber: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
|
||||
standardIds: [{ required: true, message: '请选择测试依据', trigger: 'change' }]
|
||||
reportModelId: [{ required: true, message: '请选择报告模板', trigger: 'change' }]
|
||||
}
|
||||
|
||||
const visibleProxy = computed({
|
||||
@@ -377,27 +260,12 @@ const ensureCurrentOption = (
|
||||
fallbackLabel: string
|
||||
) => {
|
||||
if (!value || options.some(option => option.value === value)) return options
|
||||
|
||||
return [...options, { label: fallbackLabel || value, value }]
|
||||
}
|
||||
|
||||
const clientUnitSelectOptions = computed(() =>
|
||||
ensureCurrentOption(props.clientUnitOptions, formModel.clientUnitId, props.record?.clientUnitName || '')
|
||||
)
|
||||
const reportModelSelectOptions = computed(() =>
|
||||
ensureCurrentOption(props.reportModelOptions, formModel.reportModelId, props.record?.reportModelName || '')
|
||||
)
|
||||
const companySelectOptions = computed(() =>
|
||||
ensureCurrentOption(props.companyOptions, formModel.createUnit, props.record?.createUnit || '')
|
||||
)
|
||||
const standardSelectOptions = computed(() => {
|
||||
const optionMap = new Map(props.standardOptions.map(option => [option.value, option]))
|
||||
const extraOptions = formModel.standardIds
|
||||
.filter(item => !optionMap.has(item))
|
||||
.map(item => ({ label: item, value: item }))
|
||||
|
||||
return [...props.standardOptions, ...extraOptions]
|
||||
})
|
||||
|
||||
const buildLogId = () => window.crypto?.randomUUID?.() || generateUUID()
|
||||
|
||||
@@ -435,13 +303,8 @@ const resetForm = () => {
|
||||
formRef.value?.clearValidate()
|
||||
formModel.id = ''
|
||||
formModel.no = ''
|
||||
formModel.clientUnitId = ''
|
||||
formModel.reportModelId = ''
|
||||
formModel.createUnit = ''
|
||||
formModel.contractNumber = ''
|
||||
formModel.standardIds = []
|
||||
formModel.data = '{}'
|
||||
formModel.phonenumber = ''
|
||||
activeDraftId.value = ''
|
||||
currentStep.value = 'import'
|
||||
logPanelExpanded.value = true
|
||||
@@ -464,17 +327,15 @@ const buildDraftId = () => {
|
||||
if (props.mode === 'edit') {
|
||||
return String(props.record?.id || '').trim()
|
||||
}
|
||||
|
||||
return window.crypto?.randomUUID?.() || generateUUID()
|
||||
}
|
||||
|
||||
const applyInitialStep = (hasPreparedLedger: boolean) => {
|
||||
if (props.mode === 'edit' && hasPreparedLedger) {
|
||||
currentStep.value = 'form'
|
||||
pushLog('info', '编辑场景检测到已有导入结果,默认进入基础信息填写步骤')
|
||||
pushLog('info', '编辑场景检测到已有导入结果,默认进入任务信息步骤')
|
||||
return
|
||||
}
|
||||
|
||||
currentStep.value = 'import'
|
||||
pushLog('info', '已进入数据导入步骤,请先完成台账校验')
|
||||
}
|
||||
@@ -482,21 +343,15 @@ const applyInitialStep = (hasPreparedLedger: boolean) => {
|
||||
const fillForm = async () => {
|
||||
try {
|
||||
const record = props.record
|
||||
const snapshot = normalizeReportTaskLedgerSnapshot(record?.data)
|
||||
const snapshot = normalizeReportTaskLedgerSnapshot(record?.data as string | null | undefined)
|
||||
|
||||
formModel.id = record?.id || ''
|
||||
formModel.no = record?.no || ''
|
||||
formModel.clientUnitId = record?.clientUnitId || ''
|
||||
formModel.reportModelId = record?.reportModelId || ''
|
||||
// 关键业务节点:编辑态详情可能返回展示名称而不是字典 value,这里必须先归一化成真实 option value,避免下拉重复补项和提交时报“检测公司不存在”。
|
||||
formModel.createUnit = resolveReportTaskOptionValue(props.companyOptions, record?.createUnit || '')
|
||||
formModel.contractNumber = record?.contractNumber || ''
|
||||
formModel.standardIds = normalizeReportTaskSelectedOptionValues(
|
||||
props.standardOptions,
|
||||
parseReportTaskStandardIds(record?.standard)
|
||||
)
|
||||
formModel.data = record?.data || '{}'
|
||||
formModel.phonenumber = record?.phonenumber || ''
|
||||
formModel.data =
|
||||
typeof record?.data === 'string' && record.data.trim()
|
||||
? record.data
|
||||
: JSON.stringify(record?.data || snapshot || {}, null, 0) || '{}'
|
||||
|
||||
activeDraftId.value = buildDraftId()
|
||||
ledgerPreparedState.value = {
|
||||
@@ -525,12 +380,11 @@ const fillForm = async () => {
|
||||
|
||||
const goToFormStep = () => {
|
||||
if (!canSubmit.value) {
|
||||
pushLog('warning', '当前校验尚未完成,不能进入基础信息填写步骤')
|
||||
pushLog('warning', '当前校验尚未完成,不能进入任务信息步骤')
|
||||
return
|
||||
}
|
||||
|
||||
currentStep.value = 'form'
|
||||
pushLog('info', '已切换到基础信息填写步骤')
|
||||
pushLog('info', '已切换到任务信息步骤')
|
||||
}
|
||||
|
||||
const goToImportStep = () => {
|
||||
@@ -540,16 +394,11 @@ const goToImportStep = () => {
|
||||
|
||||
const handleLedgerPreparedChange = (value: ReportTask.ReportTaskLedgerPreparedState) => {
|
||||
const wasPrepared = checkReportTaskLedgerPrepared(ledgerPreparedState.value)
|
||||
const nextState = {
|
||||
...value,
|
||||
draftId: activeDraftId.value
|
||||
}
|
||||
|
||||
const nextState = { ...value, draftId: activeDraftId.value }
|
||||
ledgerPreparedState.value = nextState
|
||||
|
||||
if (!wasPrepared && checkReportTaskLedgerPrepared(nextState) && currentStep.value === 'import') {
|
||||
currentStep.value = 'form'
|
||||
pushLog('success', '台账校验已完成,已自动进入基础信息填写步骤')
|
||||
pushLog('success', '台账校验已完成,已自动进入任务信息步骤')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,7 +440,6 @@ watch(
|
||||
() => props.saveSuccessVersion,
|
||||
value => {
|
||||
if (!props.visible || !value || value === lastHandledSaveSuccessVersion.value) return
|
||||
|
||||
lastHandledSaveSuccessVersion.value = value
|
||||
currentStep.value = 'done'
|
||||
pushLog('success', props.mode === 'create' ? '报告任务新增成功,流程已完成' : '报告任务编辑成功,流程已完成')
|
||||
@@ -601,34 +449,24 @@ watch(
|
||||
const submitForm = async () => {
|
||||
const valid = await formRef.value?.validate().catch(() => false)
|
||||
if (!valid) {
|
||||
pushLog('warning', '基础信息校验未通过,请检查必填项')
|
||||
pushLog('warning', '任务信息校验未通过,请检查必填项')
|
||||
return
|
||||
}
|
||||
|
||||
if (!checkReportTaskLedgerPrepared(ledgerPreparedState.value)) {
|
||||
const message = '请先完成台账校验后再提交基础信息'
|
||||
const message = '请先完成台账校验后再提交任务信息'
|
||||
ElMessage.warning(message)
|
||||
pushLog('warning', message)
|
||||
return
|
||||
}
|
||||
|
||||
pushLog(
|
||||
'info',
|
||||
props.mode === 'create'
|
||||
? '开始提交新增任务基础信息并写入台账数据'
|
||||
: '开始提交编辑后的任务基础信息并更新台账数据'
|
||||
)
|
||||
pushLog('info', props.mode === 'create' ? '开始提交新增任务' : '开始提交编辑后的任务信息')
|
||||
emit('submit', {
|
||||
id: activeDraftId.value || formModel.id || undefined,
|
||||
no: formModel.no.trim(),
|
||||
clientUnitId: formModel.clientUnitId,
|
||||
reportModelId: formModel.reportModelId,
|
||||
createUnit: formModel.createUnit,
|
||||
contractNumber: formModel.contractNumber.trim(),
|
||||
standard: stringifyReportTaskStandardIds(formModel.standardIds),
|
||||
data: JSON.parse(formModel.data.trim() || '{}'),
|
||||
batchId: ledgerPreparedState.value.batchId || undefined,
|
||||
phonenumber: formModel.phonenumber.trim() || undefined
|
||||
batchId: ledgerPreparedState.value.batchId || undefined
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -907,10 +745,6 @@ const submitForm = async () => {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.log-empty {
|
||||
padding: 18px 0;
|
||||
}
|
||||
|
||||
:deep(.report-task-flow-dialog .el-dialog__body) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<el-dialog v-model="visibleProxy" title="监测点分组" width="1120px" append-to-body destroy-on-close>
|
||||
<el-dialog v-model="visibleProxy" title="监测点分组" width="1380px" append-to-body destroy-on-close>
|
||||
<div v-loading="loading" class="report-task-group-dialog">
|
||||
<el-descriptions :column="4" border class="summary-descriptions">
|
||||
<el-descriptions-item label="报告编号">{{ resolveReportTaskText(record?.no) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="委托单位">{{ resolveReportTaskText(record?.clientUnitName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="监测点数">{{ pointList.length || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="已分组点位">{{ groupedPointCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分组数量">{{ groupedPayload.groups.length || 0 }}</el-descriptions-item>
|
||||
@@ -14,7 +13,7 @@
|
||||
<template v-else>
|
||||
<el-alert
|
||||
v-if="!groupingCompleted"
|
||||
title="请为所有监测点设置大于 0 的分组号后再保存。"
|
||||
title="台账导入时会读取 Excel 中的分组号,也可在此按需调整。当前存在未分组监测点,请补充分组号后再保存。"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
@@ -22,20 +21,8 @@
|
||||
/>
|
||||
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-title">批量分组</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-input-number
|
||||
v-model="batchGroupNo"
|
||||
:min="1"
|
||||
:step="1"
|
||||
controls-position="right"
|
||||
placeholder="分组号"
|
||||
/>
|
||||
<el-button type="primary" :disabled="!selectedPointIds.length || !batchGroupNo" @click="applyBatchGroupNo">
|
||||
应用到已选
|
||||
</el-button>
|
||||
<el-button :disabled="!selectedPointIds.length" @click="clearSelectedGroups">清空已选</el-button>
|
||||
</div>
|
||||
<div class="toolbar-title">监测点分组</div>
|
||||
<div class="toolbar-tip">分组号默认来自已导入的台账 Excel,可在此按需修改。</div>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
@@ -43,12 +30,9 @@
|
||||
row-key="id"
|
||||
border
|
||||
size="small"
|
||||
max-height="460"
|
||||
max-height="420"
|
||||
class="point-table"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column type="index" label="序号" width="70" />
|
||||
<el-table-column label="分组号" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
@@ -64,7 +48,118 @@
|
||||
<el-table-column prop="pointName" label="监测点" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="monitorTime" label="监测时间" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="voltageLevel" label="电压等级" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="excelAttachmentName" label="原始文件" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="excelAttachmentName" label="Excel原始文件" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column prop="wordAttachmentName" label="Word原始文件" min-width="220" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ resolveReportTaskText(row.wordAttachmentName) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="toolbar secondary-toolbar">
|
||||
<div class="toolbar-title">分组报告信息</div>
|
||||
<div class="toolbar-tip">这些字段允许先保存为空,执行生成报告时再由后端做完整校验。</div>
|
||||
</div>
|
||||
|
||||
<el-empty
|
||||
v-if="!groupedRows.length"
|
||||
description="请先完成监测点分组,再维护各分组的报告信息"
|
||||
:image-size="72"
|
||||
class="group-empty"
|
||||
/>
|
||||
|
||||
<el-table v-else :data="groupedRows" border size="small" max-height="420" class="group-report-table">
|
||||
<el-table-column prop="groupNo" label="分组号" width="90" />
|
||||
<el-table-column prop="pointCount" label="点位数" width="90" />
|
||||
<el-table-column label="报告编号" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
:model-value="resolveGroupField(row.groupNo, 'reportNo')"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入报告编号"
|
||||
@update:model-value="updateGroupField(row.groupNo, 'reportNo', $event)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="委托单位" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
:model-value="resolveGroupField(row.groupNo, 'clientUnitId')"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择委托单位"
|
||||
@update:model-value="updateGroupField(row.groupNo, 'clientUnitId', $event)"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in clientUnitOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检测公司" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
:model-value="resolveGroupField(row.groupNo, 'createUnit')"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择检测公司"
|
||||
@update:model-value="updateGroupField(row.groupNo, 'createUnit', $event)"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in companyOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同编号" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
:model-value="resolveGroupField(row.groupNo, 'contractNumber')"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入合同编号"
|
||||
@update:model-value="updateGroupField(row.groupNo, 'contractNumber', $event)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检测依据" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
:model-value="resolveGroupStandard(row.groupNo)"
|
||||
multiple
|
||||
filterable
|
||||
clearable
|
||||
collapse-tags
|
||||
placeholder="请选择检测依据"
|
||||
@update:model-value="updateGroupStandard(row.groupNo, $event)"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in standardOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="联系电话" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
:model-value="resolveGroupField(row.groupNo, 'phonenumber')"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入联系电话"
|
||||
@update:model-value="updateGroupField(row.groupNo, 'phonenumber', $event)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</div>
|
||||
@@ -80,22 +175,31 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import type { ReportTask } from '@/api/aireport/testReport/interface'
|
||||
import {
|
||||
checkReportTaskGroupingCompleted,
|
||||
normalizeReportTaskGroupSavePayload,
|
||||
resolveReportTaskText
|
||||
} from '../utils/testReport'
|
||||
import { normalizeReportTaskGroupSavePayload, parseReportTaskStandardIds, resolveReportTaskText } from '../utils/testReport'
|
||||
|
||||
defineOptions({
|
||||
name: 'ReportTaskGroupDialog'
|
||||
})
|
||||
|
||||
type GroupConfig = {
|
||||
reportNo: string
|
||||
clientUnitId: string
|
||||
createUnit: string
|
||||
contractNumber: string
|
||||
standard: string[]
|
||||
phonenumber: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
loading: boolean
|
||||
saving: boolean
|
||||
record: ReportTask.ReportTaskRecord | null
|
||||
pointList: ReportTask.ReportTaskPointRecord[]
|
||||
groupReports: ReportTask.ReportTaskGroupReportRecord[]
|
||||
clientUnitOptions: Array<{ label: string; value: string }>
|
||||
companyOptions: Array<{ label: string; value: string }>
|
||||
standardOptions: Array<{ label: string; value: string }>
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -104,51 +208,109 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const localPointGroupMap = ref<Record<string, number | null>>({})
|
||||
const selectedPointIds = ref<string[]>([])
|
||||
const batchGroupNo = ref<number | null>(null)
|
||||
const localGroupConfigMap = ref<Record<number, GroupConfig>>({})
|
||||
|
||||
const visibleProxy = computed({
|
||||
get: () => props.visible,
|
||||
set: value => emit('update:visible', value)
|
||||
})
|
||||
|
||||
const createEmptyGroupConfig = (): GroupConfig => ({
|
||||
reportNo: '',
|
||||
clientUnitId: '',
|
||||
createUnit: '',
|
||||
contractNumber: '',
|
||||
standard: [],
|
||||
phonenumber: ''
|
||||
})
|
||||
|
||||
const initializePointGroupMap = () => {
|
||||
const nextGroupMap: Record<string, number | null> = {}
|
||||
|
||||
props.pointList.forEach(point => {
|
||||
const pointId = String(point.id || '').trim()
|
||||
if (!pointId) return
|
||||
|
||||
const groupNo = Number(point.groupNo)
|
||||
nextGroupMap[pointId] = Number.isInteger(groupNo) && groupNo > 0 ? groupNo : null
|
||||
})
|
||||
|
||||
localPointGroupMap.value = nextGroupMap
|
||||
selectedPointIds.value = []
|
||||
batchGroupNo.value = null
|
||||
}
|
||||
|
||||
const initializeGroupConfigMap = () => {
|
||||
const nextConfigMap: Record<number, GroupConfig> = {}
|
||||
;(props.groupReports || []).forEach(groupReport => {
|
||||
const groupNo = Number(groupReport.groupNo)
|
||||
if (!Number.isInteger(groupNo) || groupNo <= 0) return
|
||||
nextConfigMap[groupNo] = {
|
||||
reportNo: String(groupReport.reportNo || ''),
|
||||
clientUnitId: String(groupReport.clientUnitId || ''),
|
||||
createUnit: String(groupReport.createUnit || ''),
|
||||
contractNumber: String(groupReport.contractNumber || ''),
|
||||
standard: parseReportTaskStandardIds(groupReport.standard),
|
||||
phonenumber: String(groupReport.phonenumber || '')
|
||||
}
|
||||
})
|
||||
localGroupConfigMap.value = nextConfigMap
|
||||
}
|
||||
|
||||
const syncGroupedConfigMap = () => {
|
||||
const activeGroupNos = new Set<number>()
|
||||
Object.values(localPointGroupMap.value).forEach(groupNo => {
|
||||
const normalizedGroupNo = Number(groupNo)
|
||||
if (Number.isInteger(normalizedGroupNo) && normalizedGroupNo > 0) {
|
||||
activeGroupNos.add(normalizedGroupNo)
|
||||
}
|
||||
})
|
||||
|
||||
const nextConfigMap: Record<number, GroupConfig> = {}
|
||||
Array.from(activeGroupNos)
|
||||
.sort((a, b) => a - b)
|
||||
.forEach(groupNo => {
|
||||
nextConfigMap[groupNo] = localGroupConfigMap.value[groupNo] || createEmptyGroupConfig()
|
||||
})
|
||||
localGroupConfigMap.value = nextConfigMap
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.visible, props.pointList],
|
||||
() => [props.visible, props.pointList, props.groupReports],
|
||||
([visible]) => {
|
||||
if (visible) {
|
||||
initializePointGroupMap()
|
||||
}
|
||||
if (!visible) return
|
||||
initializePointGroupMap()
|
||||
initializeGroupConfigMap()
|
||||
syncGroupedConfigMap()
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
const groupedPayload = computed(() => normalizeReportTaskGroupSavePayload(props.pointList, localPointGroupMap.value))
|
||||
const groupingCompleted = computed(() => checkReportTaskGroupingCompleted(props.pointList, groupedPayload.value))
|
||||
watch(
|
||||
() => localPointGroupMap.value,
|
||||
() => {
|
||||
syncGroupedConfigMap()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
const groupedPayload = computed(() => normalizeReportTaskGroupSavePayload(props.pointList, localPointGroupMap.value, localGroupConfigMap.value))
|
||||
const groupingCompleted = computed(() => {
|
||||
if (!props.pointList.length || !groupedPayload.value.groups.length) return false
|
||||
const pointIds = props.pointList.map(point => String(point.id || '').trim()).filter(Boolean)
|
||||
const groupedIds = groupedPayload.value.groups.flatMap(group => group.pointIds.map(pointId => String(pointId || '').trim()).filter(Boolean))
|
||||
if (groupedIds.length !== pointIds.length) return false
|
||||
return new Set(groupedIds).size === pointIds.length
|
||||
})
|
||||
const groupedPointCount = computed(() =>
|
||||
props.pointList.reduce((count, point) => {
|
||||
const pointId = String(point.id || '').trim()
|
||||
if (!pointId) return count
|
||||
|
||||
const groupNo = Number(localPointGroupMap.value[pointId])
|
||||
return Number.isInteger(groupNo) && groupNo > 0 ? count + 1 : count
|
||||
}, 0)
|
||||
)
|
||||
const groupedRows = computed(() =>
|
||||
groupedPayload.value.groups.map(group => ({
|
||||
groupNo: group.groupNo,
|
||||
pointCount: group.pointIds.length
|
||||
}))
|
||||
)
|
||||
|
||||
const resolvePointGroupNo = (pointId?: string) => {
|
||||
const normalizedPointId = String(pointId || '').trim()
|
||||
@@ -159,7 +321,6 @@ const resolvePointGroupNo = (pointId?: string) => {
|
||||
const updatePointGroupNo = (pointId: string | undefined, value: number | null | undefined) => {
|
||||
const normalizedPointId = String(pointId || '').trim()
|
||||
if (!normalizedPointId) return
|
||||
|
||||
const groupNo = Number(value)
|
||||
localPointGroupMap.value = {
|
||||
...localPointGroupMap.value,
|
||||
@@ -171,27 +332,42 @@ const handlePointGroupNoChange = (pointId: string | undefined, value: number | n
|
||||
updatePointGroupNo(pointId, value)
|
||||
}
|
||||
|
||||
const handleSelectionChange = (selection: ReportTask.ReportTaskPointRecord[]) => {
|
||||
selectedPointIds.value = selection.map(item => String(item.id || '').trim()).filter(Boolean)
|
||||
const ensureGroupConfig = (groupNo: number) => {
|
||||
if (!localGroupConfigMap.value[groupNo]) {
|
||||
localGroupConfigMap.value = {
|
||||
...localGroupConfigMap.value,
|
||||
[groupNo]: createEmptyGroupConfig()
|
||||
}
|
||||
}
|
||||
return localGroupConfigMap.value[groupNo]
|
||||
}
|
||||
|
||||
const applyBatchGroupNo = () => {
|
||||
const groupNo = Number(batchGroupNo.value)
|
||||
if (!Number.isInteger(groupNo) || groupNo <= 0) return
|
||||
const resolveGroupField = (groupNo: number, field: keyof Omit<GroupConfig, 'standard'>) =>
|
||||
ensureGroupConfig(groupNo)[field] || ''
|
||||
|
||||
const nextGroupMap = { ...localPointGroupMap.value }
|
||||
selectedPointIds.value.forEach(pointId => {
|
||||
nextGroupMap[pointId] = groupNo
|
||||
})
|
||||
localPointGroupMap.value = nextGroupMap
|
||||
const resolveGroupStandard = (groupNo: number) => ensureGroupConfig(groupNo).standard || []
|
||||
|
||||
const updateGroupField = (groupNo: number, field: keyof Omit<GroupConfig, 'standard'>, value: unknown) => {
|
||||
const groupConfig = ensureGroupConfig(groupNo)
|
||||
localGroupConfigMap.value = {
|
||||
...localGroupConfigMap.value,
|
||||
[groupNo]: {
|
||||
...groupConfig,
|
||||
[field]: String(value || '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const clearSelectedGroups = () => {
|
||||
const nextGroupMap = { ...localPointGroupMap.value }
|
||||
selectedPointIds.value.forEach(pointId => {
|
||||
nextGroupMap[pointId] = null
|
||||
})
|
||||
localPointGroupMap.value = nextGroupMap
|
||||
const updateGroupStandard = (groupNo: number, value: unknown) => {
|
||||
const groupConfig = ensureGroupConfig(groupNo)
|
||||
const standard = Array.isArray(value) ? value.map(item => String(item || '').trim()).filter(Boolean) : []
|
||||
localGroupConfigMap.value = {
|
||||
...localGroupConfigMap.value,
|
||||
[groupNo]: {
|
||||
...groupConfig,
|
||||
standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
@@ -206,7 +382,9 @@ const handleSubmit = () => {
|
||||
|
||||
.summary-descriptions,
|
||||
.section-alert,
|
||||
.point-table {
|
||||
.point-table,
|
||||
.group-report-table,
|
||||
.group-empty {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
@@ -219,16 +397,23 @@ const handleSubmit = () => {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.secondary-toolbar {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.toolbar-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
.toolbar-tip {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
:deep(.el-select),
|
||||
:deep(.el-input) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
:loading="detailLoading"
|
||||
:detail="detailRecord"
|
||||
:group-reports="detailGroupReports"
|
||||
:client-unit-label-map="clientUnitLabelMap"
|
||||
:company-label-map="companyLabelMap"
|
||||
:standard-label-map="standardLabelMap"
|
||||
:downloading-group-report-id="downloadingGroupReportId"
|
||||
@@ -78,6 +79,10 @@
|
||||
:saving="groupDialogSaving"
|
||||
:record="currentGroupRecord"
|
||||
:point-list="groupPointList"
|
||||
:group-reports="groupReportList"
|
||||
:client-unit-options="clientUnitOptions"
|
||||
:company-options="companyOptions"
|
||||
:standard-options="standardOptions"
|
||||
@submit="handleSaveGroups"
|
||||
/>
|
||||
</div>
|
||||
@@ -125,8 +130,6 @@ import {
|
||||
normalizeReportTaskListParams,
|
||||
normalizeReportTaskPage,
|
||||
normalizeReportTaskPointList,
|
||||
resolveReportTaskCreateUnitText,
|
||||
resolveReportTaskStandardText,
|
||||
resolveReportTaskText,
|
||||
unwrapReportTaskPayload
|
||||
} from './utils/testReport'
|
||||
@@ -154,10 +157,12 @@ const detailGroupReports = ref<ReportTask.ReportTaskGroupReportRecord[]>([])
|
||||
const currentAuditRecord = ref<ReportTask.ReportTaskRecord | null>(null)
|
||||
const currentGroupRecord = ref<ReportTask.ReportTaskRecord | null>(null)
|
||||
const groupPointList = ref<ReportTask.ReportTaskPointRecord[]>([])
|
||||
const groupReportList = ref<ReportTask.ReportTaskGroupReportRecord[]>([])
|
||||
const clientUnitOptions = ref<Array<{ label: string; value: string }>>([])
|
||||
const reportModelOptions = ref<Array<{ label: string; value: string }>>([])
|
||||
const downloadingGroupReportId = ref('')
|
||||
|
||||
const clientUnitLabelMap = computed(() => buildOptionLabelMap(clientUnitOptions.value))
|
||||
const companyOptions = computed(() => buildDictSelectOptions(dictStore.getDictData(DICT_CODES.TEST_REPORT_COMPANY)))
|
||||
const standardOptions = computed(() => buildDictSelectOptions(dictStore.getDictData(DICT_CODES.TEST_REPORT_STANDARD)))
|
||||
const companyLabelMap = computed(() => buildOptionLabelMap(companyOptions.value))
|
||||
@@ -180,7 +185,7 @@ const columns = reactive<ColumnProps<ReportTask.ReportTaskRecord>[]>([
|
||||
el: 'input',
|
||||
order: 1,
|
||||
props: {
|
||||
placeholder: '请输入报告编号、合同编号、委托单位或模板'
|
||||
placeholder: '请输入报告编号或模板'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -202,14 +207,7 @@ const columns = reactive<ColumnProps<ReportTask.ReportTaskRecord>[]>([
|
||||
}
|
||||
},
|
||||
{ prop: 'no', label: '报告编号', minWidth: 180, fixed: 'left', render: ({ row }) => resolveReportTaskText(row.no) },
|
||||
{ prop: 'clientUnitName', label: '委托单位', minWidth: 160, render: ({ row }) => resolveReportTaskText(row.clientUnitName) },
|
||||
{ prop: 'reportModelName', label: '报告模板', minWidth: 160, render: ({ row }) => resolveReportTaskText(row.reportModelName) },
|
||||
{
|
||||
prop: 'createUnit',
|
||||
label: '检测公司',
|
||||
minWidth: 160,
|
||||
render: ({ row }) => resolveReportTaskCreateUnitText(row.createUnit, companyLabelMap.value)
|
||||
},
|
||||
{
|
||||
prop: 'state',
|
||||
label: '报告状态',
|
||||
@@ -315,7 +313,6 @@ const openEditDialog = async (row: ReportTask.ReportTaskRecord) => {
|
||||
formMode.value = 'edit'
|
||||
|
||||
try {
|
||||
// 关键业务节点:编辑表单提交仍依赖原始 clientUnitId、reportModelId、createUnit、standard 等字段,不能只回填列表展示文本。
|
||||
const response = await getReportTaskDetailApi(row.id)
|
||||
currentRecord.value = unwrapReportTaskPayload<ReportTask.ReportTaskRecord>(response)
|
||||
formDialogVisible.value = true
|
||||
@@ -351,6 +348,7 @@ const openDetailDialog = async (row: ReportTask.ReportTaskRecord) => {
|
||||
return
|
||||
}
|
||||
|
||||
await ensureFormOptionsReady()
|
||||
detailRecord.value = null
|
||||
detailGroupReports.value = []
|
||||
detailDialogVisible.value = true
|
||||
@@ -378,15 +376,21 @@ const openGroupDialog = async (row: ReportTask.ReportTaskRecord) => {
|
||||
|
||||
currentGroupRecord.value = row
|
||||
groupPointList.value = []
|
||||
groupReportList.value = []
|
||||
groupDialogVisible.value = true
|
||||
groupDialogLoading.value = true
|
||||
|
||||
try {
|
||||
const response = await listReportTaskPointsApi(row.id)
|
||||
groupPointList.value = normalizeReportTaskPointList(response)
|
||||
await ensureFormOptionsReady()
|
||||
const [pointResponse, groupReportResponse] = await Promise.all([
|
||||
listReportTaskPointsApi(row.id),
|
||||
listReportTaskGroupReportsApi(row.id)
|
||||
])
|
||||
groupPointList.value = normalizeReportTaskPointList(pointResponse)
|
||||
groupReportList.value = normalizeReportTaskGroupReportList(groupReportResponse)
|
||||
} catch (error) {
|
||||
groupDialogVisible.value = false
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '监测点列表查询失败'))
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '监测点分组数据查询失败'))
|
||||
} finally {
|
||||
groupDialogLoading.value = false
|
||||
}
|
||||
@@ -565,9 +569,9 @@ const handleExport = async () => {
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await ensureReportTaskDictOptionsReady()
|
||||
await ensureFormOptionsReady()
|
||||
} catch (error) {
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '报告任务字典加载失败'))
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '报告任务关联选项加载失败'))
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -33,8 +33,10 @@ export const REPORT_TASK_GENERATE_STATE_MAP: Record<
|
||||
{ text: string; tagType: TagType }
|
||||
> = {
|
||||
0: { text: '未生成', tagType: 'info' },
|
||||
1: { text: '生成中', tagType: 'warning' },
|
||||
2: { text: '已生成', tagType: 'success' }
|
||||
1: { text: '部分成功', tagType: 'warning' },
|
||||
2: { text: '全部成功', tagType: 'success' },
|
||||
3: { text: '生成中', tagType: 'warning' },
|
||||
4: { text: '生成失败', tagType: 'danger' }
|
||||
}
|
||||
export const REPORT_TASK_GROUP_REPORT_GENERATE_STATUS_TEXT_MAP: Record<number, string> = {
|
||||
0: '未生成',
|
||||
@@ -249,7 +251,12 @@ export const normalizeReportTaskGroupReportList = (
|
||||
response as ResultData<ReportTask.ReportTaskGroupReportRecord[]>
|
||||
)
|
||||
|
||||
return Array.isArray(payload) ? payload : []
|
||||
return Array.isArray(payload)
|
||||
? payload.map(item => ({
|
||||
...item,
|
||||
standard: Array.isArray(item?.standard) ? item.standard : parseReportTaskStandardIds(item?.standard)
|
||||
}))
|
||||
: []
|
||||
}
|
||||
|
||||
export const normalizeReportTaskLedgerSnapshot = (
|
||||
@@ -391,7 +398,18 @@ export const stringifyReportTaskStandardIds = (value: string[]) =>
|
||||
|
||||
export const normalizeReportTaskGroupSavePayload = (
|
||||
pointList: ReportTask.ReportTaskPointRecord[],
|
||||
pointGroupMap: Record<string, number | string | null | undefined>
|
||||
pointGroupMap: Record<string, number | string | null | undefined>,
|
||||
groupConfigMap: Record<
|
||||
number,
|
||||
{
|
||||
reportNo?: string
|
||||
clientUnitId?: string
|
||||
createUnit?: string
|
||||
contractNumber?: string
|
||||
standard?: string[]
|
||||
phonenumber?: string
|
||||
}
|
||||
> = {}
|
||||
): ReportTask.ReportTaskGroupSaveRequest => {
|
||||
const groupedPointMap = new Map<number, string[]>()
|
||||
|
||||
@@ -413,7 +431,15 @@ export const normalizeReportTaskGroupSavePayload = (
|
||||
.sort(([groupNoA], [groupNoB]) => groupNoA - groupNoB)
|
||||
.map(([groupNo, pointIds]) => ({
|
||||
groupNo,
|
||||
pointIds
|
||||
pointIds,
|
||||
reportNo: String(groupConfigMap[groupNo]?.reportNo || '').trim() || undefined,
|
||||
clientUnitId: String(groupConfigMap[groupNo]?.clientUnitId || '').trim() || undefined,
|
||||
createUnit: String(groupConfigMap[groupNo]?.createUnit || '').trim() || undefined,
|
||||
contractNumber: String(groupConfigMap[groupNo]?.contractNumber || '').trim() || undefined,
|
||||
standard: Array.isArray(groupConfigMap[groupNo]?.standard)
|
||||
? groupConfigMap[groupNo].standard!.map(item => String(item || '').trim()).filter(Boolean)
|
||||
: [],
|
||||
phonenumber: String(groupConfigMap[groupNo]?.phonenumber || '').trim() || undefined
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
import type { ReportTask } from '@/api/aireport/testReport/interface'
|
||||
import { generateUUID } from '@/utils'
|
||||
import { normalizeReportTaskLedgerSnapshot, parseReportTaskStandardIds, stringifyReportTaskStandardIds } from './testReport'
|
||||
import { normalizeReportTaskLedgerSnapshot } from './testReport'
|
||||
|
||||
export interface ReportTaskFormModel {
|
||||
id: string
|
||||
no: string
|
||||
clientUnitId: string
|
||||
reportModelId: string
|
||||
createUnit: string
|
||||
contractNumber: string
|
||||
standardIds: string[]
|
||||
data: string
|
||||
phonenumber: string
|
||||
}
|
||||
|
||||
export const createDefaultReportTaskFormModel = (): ReportTaskFormModel => ({
|
||||
id: '',
|
||||
no: '',
|
||||
clientUnitId: '',
|
||||
reportModelId: '',
|
||||
createUnit: '',
|
||||
contractNumber: '',
|
||||
standardIds: [],
|
||||
data: '{}',
|
||||
phonenumber: ''
|
||||
data: '{}'
|
||||
})
|
||||
|
||||
export const buildReportTaskDraftId = (mode: 'create' | 'edit', record: ReportTask.ReportTaskRecord | null) => {
|
||||
@@ -40,13 +30,8 @@ export const buildReportTaskFormContext = (mode: 'create' | 'edit', record: Repo
|
||||
|
||||
formModel.id = record?.id || ''
|
||||
formModel.no = record?.no || ''
|
||||
formModel.clientUnitId = record?.clientUnitId || ''
|
||||
formModel.reportModelId = record?.reportModelId || ''
|
||||
formModel.createUnit = record?.createUnit || ''
|
||||
formModel.contractNumber = record?.contractNumber || ''
|
||||
formModel.standardIds = parseReportTaskStandardIds(record?.standard)
|
||||
formModel.data = record?.data || '{}'
|
||||
formModel.phonenumber = record?.phonenumber || ''
|
||||
formModel.data = typeof record?.data === 'string' ? record.data : JSON.stringify(record?.data || {})
|
||||
|
||||
return {
|
||||
formModel,
|
||||
@@ -62,11 +47,6 @@ export const buildReportTaskSavePayload = (
|
||||
): ReportTask.ReportTaskSaveRequest => ({
|
||||
id: draftId || formModel.id || undefined,
|
||||
no: formModel.no.trim(),
|
||||
clientUnitId: formModel.clientUnitId,
|
||||
reportModelId: formModel.reportModelId,
|
||||
createUnit: formModel.createUnit,
|
||||
contractNumber: formModel.contractNumber.trim(),
|
||||
standard: stringifyReportTaskStandardIds(formModel.standardIds),
|
||||
data: JSON.parse(formModel.data.trim() || '{}'),
|
||||
phonenumber: formModel.phonenumber.trim() || undefined
|
||||
data: JSON.parse(formModel.data.trim() || '{}')
|
||||
})
|
||||
|
||||
@@ -96,18 +96,6 @@
|
||||
<el-input v-model="item.no" maxlength="32" clearable placeholder="请输入报告编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="委托单位" required>
|
||||
<el-select v-model="item.clientUnitId" filterable clearable placeholder="请选择委托单位">
|
||||
<el-option
|
||||
v-for="option in clientUnitOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="报告模板" required>
|
||||
<el-select v-model="item.reportModelId" filterable clearable placeholder="请选择报告模板">
|
||||
@@ -120,47 +108,6 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="检测公司" required>
|
||||
<el-select v-model="item.createUnit" filterable clearable placeholder="请选择检测公司">
|
||||
<el-option
|
||||
v-for="option in companyOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="合同编号" required>
|
||||
<el-input v-model="item.contractNumber" maxlength="32" clearable placeholder="请输入合同编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="联系电话">
|
||||
<el-input v-model="item.phonenumber" maxlength="32" clearable placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24">
|
||||
<el-form-item label="检测依据" required>
|
||||
<el-select
|
||||
v-model="item.standard"
|
||||
multiple
|
||||
filterable
|
||||
clearable
|
||||
collapse-tags
|
||||
placeholder="请选择检测依据"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in standardOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -202,10 +149,7 @@ const props = defineProps<{
|
||||
zipValidating: boolean
|
||||
createSaving: boolean
|
||||
validateResult: ReportTaskMulti.ReportTaskMultiValidateResult | null
|
||||
clientUnitOptions: SelectOption[]
|
||||
reportModelOptions: SelectOption[]
|
||||
companyOptions: SelectOption[]
|
||||
standardOptions: SelectOption[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -252,12 +196,7 @@ const buildChildConfigForms = (templateDirs: ReportTaskMulti.ReportTaskMultiTemp
|
||||
templateDirName: String(item.dirName || ''),
|
||||
templateDirPath: String(item.dirPath || ''),
|
||||
no: '',
|
||||
clientUnitId: '',
|
||||
reportModelId: '',
|
||||
createUnit: '',
|
||||
contractNumber: '',
|
||||
standard: [],
|
||||
phonenumber: '',
|
||||
pointCount: Number(item.pointCount || 0),
|
||||
groupCount: Number(item.groupCount || 0),
|
||||
excelAttachmentCount: Number(item.excelAttachmentCount || 0),
|
||||
@@ -313,11 +252,7 @@ const validateCreateForm = () => {
|
||||
|
||||
for (const item of createForm.childReports) {
|
||||
if (!item.no.trim()) return `模板目录 ${item.templateDirName} 缺少报告编号`
|
||||
if (!item.clientUnitId) return `模板目录 ${item.templateDirName} 缺少委托单位`
|
||||
if (!item.reportModelId) return `模板目录 ${item.templateDirName} 缺少报告模板`
|
||||
if (!item.createUnit) return `模板目录 ${item.templateDirName} 缺少检测公司`
|
||||
if (!item.contractNumber.trim()) return `模板目录 ${item.templateDirName} 缺少合同编号`
|
||||
if (!item.standard.length) return `模板目录 ${item.templateDirName} 缺少检测依据`
|
||||
}
|
||||
|
||||
return ''
|
||||
@@ -337,12 +272,7 @@ const handleCreate = () => {
|
||||
templateDirName: item.templateDirName,
|
||||
templateDirPath: item.templateDirPath,
|
||||
no: item.no.trim(),
|
||||
clientUnitId: item.clientUnitId,
|
||||
reportModelId: item.reportModelId,
|
||||
createUnit: item.createUnit,
|
||||
contractNumber: item.contractNumber.trim(),
|
||||
standard: item.standard,
|
||||
phonenumber: item.phonenumber?.trim() || undefined
|
||||
reportModelId: item.reportModelId
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
:zip-validating="zipValidating"
|
||||
:create-saving="createSaving"
|
||||
:validate-result="zipValidateResult"
|
||||
:client-unit-options="clientUnitOptions"
|
||||
:report-model-options="reportModelOptions"
|
||||
:company-options="companyOptions"
|
||||
:standard-options="standardOptions"
|
||||
@validate-zip="handleValidateZip"
|
||||
@create="handleCreateMulti"
|
||||
@reset="resetCreateDialogState"
|
||||
@@ -96,6 +93,7 @@
|
||||
:loading="childDetailLoading"
|
||||
:detail="childDetailRecord"
|
||||
:group-reports="childDetailGroupReports"
|
||||
:client-unit-label-map="clientUnitLabelMap"
|
||||
:company-label-map="companyLabelMap"
|
||||
:standard-label-map="standardLabelMap"
|
||||
:downloading-group-report-id="downloadingGroupReportId"
|
||||
@@ -108,6 +106,10 @@
|
||||
:saving="childGroupSaving"
|
||||
:record="currentChildGroupRecord"
|
||||
:point-list="childGroupPointList"
|
||||
:group-reports="childGroupReports"
|
||||
:client-unit-options="clientUnitOptions"
|
||||
:company-options="companyOptions"
|
||||
:standard-options="standardOptions"
|
||||
@submit="handleSaveChildGroups"
|
||||
/>
|
||||
</div>
|
||||
@@ -192,6 +194,7 @@ const detailRecord = ref<ReportTaskMulti.ReportTaskMultiRecord | null>(null)
|
||||
const detailChildReports = ref<ReportTask.ReportTaskRecord[]>([])
|
||||
const childDetailRecord = ref<ReportTask.ReportTaskRecord | null>(null)
|
||||
const childDetailGroupReports = ref<ReportTask.ReportTaskGroupReportRecord[]>([])
|
||||
const childGroupReports = ref<ReportTask.ReportTaskGroupReportRecord[]>([])
|
||||
const downloadingMultiId = ref('')
|
||||
const downloadingGroupReportId = ref('')
|
||||
const currentChildGroupRecord = ref<ReportTask.ReportTaskRecord | null>(null)
|
||||
@@ -199,6 +202,7 @@ const childGroupPointList = ref<ReportTask.ReportTaskPointRecord[]>([])
|
||||
const clientUnitOptions = ref<Array<{ label: string; value: string }>>([])
|
||||
const reportModelOptions = ref<Array<{ label: string; value: string }>>([])
|
||||
|
||||
const clientUnitLabelMap = computed(() => buildOptionLabelMap(clientUnitOptions.value))
|
||||
const companyOptions = computed(() => buildDictSelectOptions(dictStore.getDictData(DICT_CODES.TEST_REPORT_COMPANY)))
|
||||
const standardOptions = computed(() => buildDictSelectOptions(dictStore.getDictData(DICT_CODES.TEST_REPORT_STANDARD)))
|
||||
const companyLabelMap = computed(() => buildOptionLabelMap(companyOptions.value))
|
||||
@@ -415,6 +419,7 @@ const openChildDetailDialog = async (row: ReportTask.ReportTaskRecord) => {
|
||||
childDetailDialogVisible.value = true
|
||||
childDetailLoading.value = true
|
||||
try {
|
||||
await ensureCreateOptionsReady()
|
||||
const [detailResponse, groupReportsResponse] = await Promise.all([
|
||||
getReportTaskDetailApi(reportId),
|
||||
listReportTaskGroupReportsApi(reportId)
|
||||
@@ -439,14 +444,20 @@ const openChildGroupDialog = async (row: ReportTask.ReportTaskRecord) => {
|
||||
}
|
||||
currentChildGroupRecord.value = row
|
||||
childGroupPointList.value = []
|
||||
childGroupReports.value = []
|
||||
childGroupDialogVisible.value = true
|
||||
childGroupLoading.value = true
|
||||
try {
|
||||
const response = await listReportTaskPointsApi(reportId)
|
||||
childGroupPointList.value = normalizeReportTaskPointList(response)
|
||||
await ensureCreateOptionsReady()
|
||||
const [pointResponse, groupReportResponse] = await Promise.all([
|
||||
listReportTaskPointsApi(reportId),
|
||||
listReportTaskGroupReportsApi(reportId)
|
||||
])
|
||||
childGroupPointList.value = normalizeReportTaskPointList(pointResponse)
|
||||
childGroupReports.value = normalizeReportTaskGroupReportList(groupReportResponse)
|
||||
} catch (error) {
|
||||
childGroupDialogVisible.value = false
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '子报告监测点查询失败'))
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '子报告分组数据查询失败'))
|
||||
} finally {
|
||||
childGroupLoading.value = false
|
||||
}
|
||||
@@ -560,7 +571,7 @@ const handleBatchDelete = async (ids: string[]) => {
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await ensureDictOptionsReady()
|
||||
await Promise.all([ensureDictOptionsReady(), loadClientUnitOptions()])
|
||||
} catch (error) {
|
||||
ElMessage.error(getReportTaskErrorMessage(error, '字典加载失败'))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user