fix(ai-report): 修复报告任务表单字段长度限制和选项值处理问题
This commit is contained in:
@@ -41,16 +41,32 @@
|
||||
|
||||
<div v-else-if="currentStep === 'form'" class="flow-panel">
|
||||
<div class="form-panel">
|
||||
<el-form ref="formRef" :model="formModel" :rules="formRules" label-width="108px" class="report-task-form">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formModel"
|
||||
: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="formModel.no" maxlength="32" clearable placeholder="请输入报告编号" />
|
||||
<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-select
|
||||
v-model="formModel.clientUnitId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择委托单位"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in clientUnitSelectOptions"
|
||||
:key="option.value"
|
||||
@@ -62,7 +78,12 @@
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="报告模板" prop="reportModelId">
|
||||
<el-select v-model="formModel.reportModelId" filterable clearable placeholder="请选择报告模板">
|
||||
<el-select
|
||||
v-model="formModel.reportModelId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择报告模板"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in reportModelSelectOptions"
|
||||
:key="option.value"
|
||||
@@ -74,7 +95,12 @@
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="检测公司" prop="createUnit">
|
||||
<el-select v-model="formModel.createUnit" filterable clearable placeholder="请选择检测公司">
|
||||
<el-select
|
||||
v-model="formModel.createUnit"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择检测公司"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in companySelectOptions"
|
||||
:key="option.value"
|
||||
@@ -86,7 +112,12 @@
|
||||
</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-input
|
||||
v-model="formModel.contractNumber"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入合同编号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12">
|
||||
@@ -110,7 +141,12 @@
|
||||
</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-input
|
||||
v-model="formModel.phonenumber"
|
||||
maxlength="32"
|
||||
clearable
|
||||
placeholder="请输入联系电话"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -157,7 +193,9 @@
|
||||
</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="汇总文件">
|
||||
{{ importSummary.summaryFileName }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</div>
|
||||
@@ -165,29 +203,37 @@
|
||||
|
||||
<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>
|
||||
|
||||
<div v-show="logPanelExpanded" class="log-panel-body">
|
||||
<div class="log-popover-body">
|
||||
<div v-if="logEntries.length" class="log-list">
|
||||
<div v-for="entry in logEntries" :key="entry.id" class="log-item">
|
||||
<div class="log-meta">
|
||||
<el-tag size="small" :type="resolveLogTagType(entry.type)">{{ resolveLogTypeText(entry.type) }}</el-tag>
|
||||
<span class="log-time">{{ entry.time }}</span>
|
||||
<div v-if="logEntries.length" class="log-list">
|
||||
<div v-for="entry in logEntries" :key="entry.id" class="log-item">
|
||||
<div class="log-meta">
|
||||
<el-tag size="small" :type="resolveLogTagType(entry.type)">
|
||||
{{ resolveLogTypeText(entry.type) }}
|
||||
</el-tag>
|
||||
<span class="log-time">{{ entry.time }}</span>
|
||||
</div>
|
||||
<div class="log-message">{{ entry.message }}</div>
|
||||
</div>
|
||||
<div class="log-message">{{ entry.message }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else description="当前暂无日志输出" :image-size="60" />
|
||||
<el-empty v-else description="当前暂无日志输出" :image-size="60" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button :disabled="saving" @click="visibleProxy = false">{{ currentStep === 'done' ? '关闭' : '取消' }}</el-button>
|
||||
<el-button :disabled="saving" @click="visibleProxy = false">
|
||||
{{ currentStep === 'done' ? '关闭' : '取消' }}
|
||||
</el-button>
|
||||
|
||||
<template v-if="currentStep === 'import'">
|
||||
<el-button type="primary" :disabled="!canSubmit" @click="goToFormStep">下一步</el-button>
|
||||
@@ -211,7 +257,9 @@ import {
|
||||
checkReportTaskLedgerPrepared,
|
||||
getReportTaskErrorMessage,
|
||||
normalizeReportTaskLedgerSnapshot,
|
||||
normalizeReportTaskSelectedOptionValues,
|
||||
parseReportTaskStandardIds,
|
||||
resolveReportTaskOptionValue,
|
||||
stringifyReportTaskStandardIds
|
||||
} from '../utils/testReport'
|
||||
|
||||
@@ -432,9 +480,13 @@ const fillForm = async () => {
|
||||
formModel.no = record?.no || ''
|
||||
formModel.clientUnitId = record?.clientUnitId || ''
|
||||
formModel.reportModelId = record?.reportModelId || ''
|
||||
formModel.createUnit = record?.createUnit || ''
|
||||
// 关键业务节点:编辑态详情可能返回展示名称而不是字典 value,这里必须先归一化成真实 option value,避免下拉重复补项和提交时报“检测公司不存在”。
|
||||
formModel.createUnit = resolveReportTaskOptionValue(props.companyOptions, record?.createUnit || '')
|
||||
formModel.contractNumber = record?.contractNumber || ''
|
||||
formModel.standardIds = parseReportTaskStandardIds(record?.standard)
|
||||
formModel.standardIds = normalizeReportTaskSelectedOptionValues(
|
||||
props.standardOptions,
|
||||
parseReportTaskStandardIds(record?.standard)
|
||||
)
|
||||
formModel.data = record?.data || '{}'
|
||||
formModel.phonenumber = record?.phonenumber || ''
|
||||
|
||||
@@ -548,7 +600,12 @@ const submitForm = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
pushLog('info', props.mode === 'create' ? '开始提交新增任务基础信息并写入台账数据' : '开始提交编辑后的任务基础信息并更新台账数据')
|
||||
pushLog(
|
||||
'info',
|
||||
props.mode === 'create'
|
||||
? '开始提交新增任务基础信息并写入台账数据'
|
||||
: '开始提交编辑后的任务基础信息并更新台账数据'
|
||||
)
|
||||
emit('submit', {
|
||||
id: activeDraftId.value || formModel.id || undefined,
|
||||
no: formModel.no.trim(),
|
||||
@@ -891,6 +948,5 @@ const submitForm = async () => {
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,10 @@ export const REPORT_TASK_STATE_OPTIONS: Array<{ label: string; value: ReportTask
|
||||
{ label: '已退回', value: '04' },
|
||||
{ label: '已删除', value: '05' }
|
||||
]
|
||||
export const REPORT_TASK_GENERATE_STATE_MAP: Record<ReportTask.ReportTaskGenerateState, { text: string; tagType: TagType }> = {
|
||||
export const REPORT_TASK_GENERATE_STATE_MAP: Record<
|
||||
ReportTask.ReportTaskGenerateState,
|
||||
{ text: string; tagType: TagType }
|
||||
> = {
|
||||
0: { text: '未生成', tagType: 'info' },
|
||||
1: { text: '生成中', tagType: 'warning' },
|
||||
2: { text: '已生成', tagType: 'success' }
|
||||
@@ -43,11 +46,11 @@ export const REPORT_TASK_GROUP_REPORT_GENERATE_STATUS_TAG_TYPE_MAP: Record<
|
||||
number,
|
||||
'warning' | 'success' | 'danger' | undefined
|
||||
> = {
|
||||
0: undefined,
|
||||
1: 'warning',
|
||||
2: 'success',
|
||||
3: 'danger'
|
||||
}
|
||||
0: undefined,
|
||||
1: 'warning',
|
||||
2: 'success',
|
||||
3: 'danger'
|
||||
}
|
||||
|
||||
export const resolveReportTaskText = (value: unknown) => {
|
||||
if (value === null || value === undefined) return '-'
|
||||
@@ -103,18 +106,27 @@ export const getReportTaskErrorMessage = (error: unknown, fallback: string) => {
|
||||
}
|
||||
|
||||
export const isReportTaskExcelFileName = (fileName: string) => {
|
||||
const normalizedName = String(fileName || '').trim().toLowerCase()
|
||||
const normalizedName = String(fileName || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
return TEST_REPORT_EXCEL_EXTENSIONS.some(extension => normalizedName.endsWith(extension))
|
||||
}
|
||||
|
||||
export const isReportTaskWordFileName = (fileName: string) => {
|
||||
const normalizedName = String(fileName || '').trim().toLowerCase()
|
||||
const normalizedName = String(fileName || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
return TEST_REPORT_WORD_EXTENSIONS.some(extension => normalizedName.endsWith(extension))
|
||||
}
|
||||
|
||||
export const isReportTaskLedgerSummaryFileName = (fileName: string) => {
|
||||
const normalizedName = String(fileName || '').trim().toLowerCase()
|
||||
return normalizedName.includes(TEST_REPORT_LEDGER_SUMMARY_FILE_BASE_NAME.toLowerCase()) && isReportTaskExcelFileName(normalizedName)
|
||||
const normalizedName = String(fileName || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
return (
|
||||
normalizedName.includes(TEST_REPORT_LEDGER_SUMMARY_FILE_BASE_NAME.toLowerCase()) &&
|
||||
isReportTaskExcelFileName(normalizedName)
|
||||
)
|
||||
}
|
||||
|
||||
export const isReportTaskLedgerAttachmentFileName = (fileName: string) =>
|
||||
@@ -132,10 +144,7 @@ export const normalizeReportTaskPointList = (
|
||||
|
||||
export const normalizeReportTaskLedgerImportResult = (
|
||||
response:
|
||||
| ResultData<ReportTask.ReportTaskLedgerImportResult>
|
||||
| ReportTask.ReportTaskLedgerImportResult
|
||||
| null
|
||||
| undefined
|
||||
ResultData<ReportTask.ReportTaskLedgerImportResult> | ReportTask.ReportTaskLedgerImportResult | null | undefined
|
||||
): ReportTask.ReportTaskLedgerImportResult => {
|
||||
const payload = unwrapReportTaskPayload<ReportTask.ReportTaskLedgerImportResult | null | undefined>(
|
||||
response as ResultData<ReportTask.ReportTaskLedgerImportResult>
|
||||
@@ -193,7 +202,9 @@ export const normalizeReportTaskLedgerValidateResult = (
|
||||
requiredSheets: Array.isArray(payload?.requiredSheets) ? payload.requiredSheets.filter(Boolean) : [],
|
||||
existingSheets: Array.isArray(payload?.existingSheets) ? payload.existingSheets.filter(Boolean) : [],
|
||||
missingSheets: Array.isArray(payload?.missingSheets) ? payload.missingSheets.filter(Boolean) : [],
|
||||
orphanAttachmentNames: Array.isArray(payload?.orphanAttachmentNames) ? payload.orphanAttachmentNames.filter(Boolean) : [],
|
||||
orphanAttachmentNames: Array.isArray(payload?.orphanAttachmentNames)
|
||||
? payload.orphanAttachmentNames.filter(Boolean)
|
||||
: [],
|
||||
failReasons: Array.isArray(payload?.failReasons) ? payload.failReasons.filter(Boolean) : [],
|
||||
points: Array.isArray(payload?.points)
|
||||
? payload.points.map(point => ({
|
||||
@@ -308,9 +319,8 @@ export const getReportTaskGenerateStateText = (state?: number | null) =>
|
||||
export const getReportTaskGenerateStateTagType = (state?: number | null): TagType =>
|
||||
REPORT_TASK_GENERATE_STATE_MAP[state as ReportTask.ReportTaskGenerateState]?.tagType || 'info'
|
||||
|
||||
export const checkReportTaskLedgerPrepared = (
|
||||
state: ReportTask.ReportTaskLedgerPreparedState | null | undefined
|
||||
) => Boolean(state?.draftId && state.hasImported && !state.pendingRevalidate)
|
||||
export const checkReportTaskLedgerPrepared = (state: ReportTask.ReportTaskLedgerPreparedState | null | undefined) =>
|
||||
Boolean(state?.draftId && state.hasImported && !state.pendingRevalidate)
|
||||
|
||||
export const buildDictSelectOptions = (dictData: Dict[] = []) =>
|
||||
dictData
|
||||
@@ -326,6 +336,32 @@ export const buildOptionLabelMap = (options: Array<{ label: string; value: strin
|
||||
return result
|
||||
}, {})
|
||||
|
||||
export const resolveReportTaskOptionValue = (
|
||||
options: Array<{ label: string; value: string }>,
|
||||
value?: string | null
|
||||
) => {
|
||||
const text = String(value || '').trim()
|
||||
if (!text) return ''
|
||||
|
||||
const matchedByValue = options.find(option => option.value === text)
|
||||
if (matchedByValue) return matchedByValue.value
|
||||
|
||||
const matchedByLabel = options.find(option => option.label === text)
|
||||
return matchedByLabel?.value || text
|
||||
}
|
||||
|
||||
export const normalizeReportTaskSelectedOptionValues = (
|
||||
options: Array<{ label: string; value: string }>,
|
||||
values: string[] = []
|
||||
) =>
|
||||
values.reduce<string[]>((result, value) => {
|
||||
const normalizedValue = resolveReportTaskOptionValue(options, value)
|
||||
if (normalizedValue && !result.includes(normalizedValue)) {
|
||||
result.push(normalizedValue)
|
||||
}
|
||||
return result
|
||||
}, [])
|
||||
|
||||
export const parseReportTaskStandardIds = (value?: string[] | string | null) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(item => String(item).trim()).filter(Boolean)
|
||||
@@ -387,7 +423,9 @@ export const checkReportTaskGroupingCompleted = (
|
||||
const pointIds = pointList.map(point => String(point.id || '').trim()).filter(Boolean)
|
||||
if (!pointIds.length) return false
|
||||
|
||||
const groupedIds = payload.groups.flatMap(group => group.pointIds.map(pointId => String(pointId || '').trim()).filter(Boolean))
|
||||
const groupedIds = payload.groups.flatMap(group =>
|
||||
group.pointIds.map(pointId => String(pointId || '').trim()).filter(Boolean)
|
||||
)
|
||||
if (groupedIds.length !== pointIds.length) return false
|
||||
|
||||
const uniqueGroupedIds = new Set(groupedIds)
|
||||
@@ -397,7 +435,9 @@ export const checkReportTaskGroupingCompleted = (
|
||||
const hasInvalidPointId = Array.from(uniqueGroupedIds).some(pointId => !pointIdSet.has(pointId))
|
||||
if (hasInvalidPointId) return false
|
||||
|
||||
return payload.groups.every(group => Number.isInteger(group.groupNo) && group.groupNo > 0 && group.pointIds.length > 0)
|
||||
return payload.groups.every(
|
||||
group => Number.isInteger(group.groupNo) && group.groupNo > 0 && group.pointIds.length > 0
|
||||
)
|
||||
}
|
||||
|
||||
export const resolveReportTaskCreateUnitText = (
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
<el-input :value="dictTypeName" disabled/>
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" :label-width="100" prop="name">
|
||||
<el-input v-model="formContent.name" placeholder="请输入" autocomplete="off" maxlength="32" show-word-limit/>
|
||||
<el-input v-model="formContent.name" placeholder="请输入" autocomplete="off" maxlength="64" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item label="编码" :label-width="100" prop="code">
|
||||
<el-input v-model="formContent.code" placeholder="请输入" autocomplete="off" maxlength="32" show-word-limit/>
|
||||
<el-input v-model="formContent.code" placeholder="请输入" autocomplete="off" maxlength="30" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启值描述" :label-width="100" >
|
||||
<el-radio-group v-model="formContent.openValue" @change="handleOpenValueChange">
|
||||
|
||||
Reference in New Issue
Block a user