feat(mmsMapping): 完善ICD路径校验功能
- 添加ICD路径校验契约测试用例验证功能完整性 - 实现ICD校验一致性检查仅在需要时注入标准映射JSON - 添加ICD校验动作按钮样式与主要操作按钮保持一致 - 实现ICD激活前验证映射JSON存在性确保数据完整 - 添加ICD页面独立获取活动标准记录功能避免过滤影响 - 实现上传文件名自动填充缺失路径提升用户体验 - 添加非标准和上游ICD类型一致性校验动作显示 - 实现ICD校验结果成功失败状态指示器显示 - 分离JSON映射问题与ICD一致性问题分别处理 - 使用JSON就绪状态替代保存就绪进行校验判断 - 添加XML映射完成前保存校验结果前置条件验证 - 重构ICD校验对话框保存步骤逻辑优化流程 - 扩展ICD校验消息类型支持对象格式详情展示 - 添加校验结果中解析ICD文档回写到路径记录 - 修复映射结果面板国际化文本乱码问题 - 添加ICD一致性问题列表单独弹窗显示功能 - 实现ICD校验状态指示器交互式问题查看 - 更新序列配置界面国际化文本提升可用性 - 重构问题列表标签文本支持动态计数显示 - 优化JSON映射序列配置搜索和展示功能 - 修正ICD校验保存逻辑确保数据验证完整性
This commit is contained in:
@@ -148,6 +148,14 @@ export namespace MmsMapping {
|
|||||||
canCheckPqdif?: boolean
|
canCheckPqdif?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IcdCheckMsg {
|
||||||
|
summary?: string
|
||||||
|
details?: string[]
|
||||||
|
issuesJson?: string
|
||||||
|
correctedJson?: string
|
||||||
|
[key: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateDeviceTypeRequest {
|
export interface CreateDeviceTypeRequest {
|
||||||
name: string
|
name: string
|
||||||
icd?: string
|
icd?: string
|
||||||
@@ -164,10 +172,12 @@ export namespace MmsMapping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SaveIcdCheckResultRequest {
|
export interface SaveIcdCheckResultRequest {
|
||||||
|
icd?: string
|
||||||
|
icdDocument?: IcdDocument
|
||||||
mappingJson?: string
|
mappingJson?: string
|
||||||
xml?: string
|
xml?: string
|
||||||
result: number
|
result: number
|
||||||
msg?: string
|
msg?: IcdCheckMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IcdPathRecord {
|
export interface IcdPathRecord {
|
||||||
@@ -180,7 +190,7 @@ export namespace MmsMapping {
|
|||||||
jsonStr?: string
|
jsonStr?: string
|
||||||
xmlStr?: string
|
xmlStr?: string
|
||||||
result?: number
|
result?: number
|
||||||
msg?: string
|
msg?: IcdCheckMsg | string
|
||||||
type?: number
|
type?: number
|
||||||
referenceIcdId?: string
|
referenceIcdId?: string
|
||||||
createBy?: string
|
createBy?: string
|
||||||
@@ -218,10 +228,12 @@ export namespace MmsMapping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SaveIcdPathCheckResultRequest {
|
export interface SaveIcdPathCheckResultRequest {
|
||||||
|
icd?: string
|
||||||
|
icdDocument?: IcdDocument
|
||||||
mappingJson?: string
|
mappingJson?: string
|
||||||
xml?: string
|
xml?: string
|
||||||
result?: number
|
result?: number
|
||||||
msg?: string
|
msg?: IcdCheckMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IcdJsonConsistencyCheckRequest {
|
export interface IcdJsonConsistencyCheckRequest {
|
||||||
|
|||||||
@@ -66,6 +66,8 @@
|
|||||||
:problem-tab-label="problemTabLabel"
|
:problem-tab-label="problemTabLabel"
|
||||||
:problem-list="problemList"
|
:problem-list="problemList"
|
||||||
:problem-empty-text="problemEmptyText"
|
:problem-empty-text="problemEmptyText"
|
||||||
|
:icd-consistency-problem-list="icdConsistencyProblemList"
|
||||||
|
:icd-consistency-problem-empty-text="icdConsistencyProblemEmptyText"
|
||||||
:method-describe="methodDescribe"
|
:method-describe="methodDescribe"
|
||||||
:can-export-json-mapping="canExportJsonMapping"
|
:can-export-json-mapping="canExportJsonMapping"
|
||||||
:can-export-xml-mapping="canExportXmlMapping"
|
:can-export-xml-mapping="canExportXmlMapping"
|
||||||
@@ -76,9 +78,11 @@
|
|||||||
:sequence-dialog-visible="sequenceDialogVisible"
|
:sequence-dialog-visible="sequenceDialogVisible"
|
||||||
:show-save-icd-check-result="showSaveIcdCheckResult"
|
:show-save-icd-check-result="showSaveIcdCheckResult"
|
||||||
:show-icd-check-action="showConsistencyCheck"
|
:show-icd-check-action="showConsistencyCheck"
|
||||||
|
:can-run-icd-consistency-check="canRunIcdConsistencyCheck"
|
||||||
:can-save-icd-check-result="canSaveIcdCheckResult"
|
:can-save-icd-check-result="canSaveIcdCheckResult"
|
||||||
:is-saving-icd-check-result="isSavingIcdCheckResult"
|
:is-saving-icd-check-result="isSavingIcdCheckResult"
|
||||||
:save-icd-check-result-text="saveIcdCheckResultText"
|
:save-icd-check-result-text="saveIcdCheckResultText"
|
||||||
|
:icd-consistency-status="icdConsistencyStatus"
|
||||||
:show-description="false"
|
:show-description="false"
|
||||||
@export-mapping="handleExportMapping"
|
@export-mapping="handleExportMapping"
|
||||||
@generate-xml-mapping="handleGenerateXmlMapping"
|
@generate-xml-mapping="handleGenerateXmlMapping"
|
||||||
@@ -130,7 +134,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const dialogTitle = computed(() => (props.icdPathName ? `ICD校验:${props.icdPathName}` : 'ICD校验'))
|
const dialogTitle = computed(() => (props.icdPathName ? `ICD校验:${props.icdPathName}` : 'ICD校验'))
|
||||||
const showConsistencyCheck = computed(() => props.icdPathType === 1 || props.icdPathType === 3)
|
const showConsistencyCheck = computed(() => props.icdPathType === 2 || props.icdPathType === 3)
|
||||||
|
|
||||||
const saveIcdCheckResult = (params: MmsMapping.SaveIcdCheckResultRequest): Promise<ResultData<boolean> | boolean> => {
|
const saveIcdCheckResult = (params: MmsMapping.SaveIcdCheckResultRequest): Promise<ResultData<boolean> | boolean> => {
|
||||||
return saveIcdPathCheckResultApi(props.icdPathId, params)
|
return saveIcdPathCheckResultApi(props.icdPathId, params)
|
||||||
@@ -163,6 +167,8 @@ const {
|
|||||||
problemTabLabel,
|
problemTabLabel,
|
||||||
problemList,
|
problemList,
|
||||||
problemEmptyText,
|
problemEmptyText,
|
||||||
|
icdConsistencyProblemList,
|
||||||
|
icdConsistencyProblemEmptyText,
|
||||||
methodDescribe,
|
methodDescribe,
|
||||||
canExportJsonMapping,
|
canExportJsonMapping,
|
||||||
canExportXmlMapping,
|
canExportXmlMapping,
|
||||||
@@ -172,10 +178,12 @@ const {
|
|||||||
showXmlMappingTab,
|
showXmlMappingTab,
|
||||||
sequenceDialogVisible,
|
sequenceDialogVisible,
|
||||||
showSaveIcdCheckResult,
|
showSaveIcdCheckResult,
|
||||||
|
canRunIcdConsistencyCheck,
|
||||||
canSaveIcdCheckResult,
|
canSaveIcdCheckResult,
|
||||||
isSavingIcdCheckResult,
|
isSavingIcdCheckResult,
|
||||||
saveIcdCheckResultText,
|
saveIcdCheckResultText,
|
||||||
hasIcdConsistencyCheckResult,
|
hasIcdConsistencyCheckResult,
|
||||||
|
icdConsistencyStatus,
|
||||||
confirmDialogVisible,
|
confirmDialogVisible,
|
||||||
isConfirmingSelection,
|
isConfirmingSelection,
|
||||||
handleIcdFileChange,
|
handleIcdFileChange,
|
||||||
@@ -192,8 +200,9 @@ const {
|
|||||||
} = useMmsMappingFlow({
|
} = useMmsMappingFlow({
|
||||||
deviceTypeCheckId: toRef(props, 'icdPathId'),
|
deviceTypeCheckId: toRef(props, 'icdPathId'),
|
||||||
deviceTypeCheckName: toRef(props, 'icdPathName'),
|
deviceTypeCheckName: toRef(props, 'icdPathName'),
|
||||||
standardMappingJson: computed(() => props.activeIcdPathRecord?.jsonStr?.trim() || ''),
|
// 关键业务节点:只有需要一致性校验的 ICD 类型才注入标准 JSON,避免隐藏校验按钮后保存仍被校验前置条件卡住。
|
||||||
standardMappingName: computed(() => props.activeIcdPathRecord?.name?.trim() || ''),
|
standardMappingJson: computed(() => (showConsistencyCheck.value ? props.activeIcdPathRecord?.jsonStr?.trim() || '' : '')),
|
||||||
|
standardMappingName: computed(() => (showConsistencyCheck.value ? props.activeIcdPathRecord?.name?.trim() || '' : '')),
|
||||||
saveIcdCheckResult,
|
saveIcdCheckResult,
|
||||||
onIcdCheckSaved: () => {
|
onIcdCheckSaved: () => {
|
||||||
emit('saved')
|
emit('saved')
|
||||||
@@ -233,6 +242,10 @@ const activeStepIndex = computed(() => {
|
|||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const canReachSaveStep = computed(() =>
|
||||||
|
showConsistencyCheck.value ? hasIcdConsistencyCheckResult.value : hasXmlMapping.value
|
||||||
|
)
|
||||||
|
|
||||||
const icdCheckFlowSteps = computed<IcdCheckFlowStep[]>(() => {
|
const icdCheckFlowSteps = computed<IcdCheckFlowStep[]>(() => {
|
||||||
const steps = [
|
const steps = [
|
||||||
createFlowStep(
|
createFlowStep(
|
||||||
@@ -284,8 +297,14 @@ const icdCheckFlowSteps = computed<IcdCheckFlowStep[]>(() => {
|
|||||||
steps.push(
|
steps.push(
|
||||||
createFlowStep(
|
createFlowStep(
|
||||||
'保存',
|
'保存',
|
||||||
isSavingIcdCheckResult.value ? '正在保存校验结果' : hasXmlMapping.value ? '可保存校验结果' : '等待XML映射',
|
isSavingIcdCheckResult.value
|
||||||
isSavingIcdCheckResult.value ? 'process' : 'wait'
|
? '正在保存校验结果'
|
||||||
|
: canReachSaveStep.value
|
||||||
|
? '可保存校验结果'
|
||||||
|
: showConsistencyCheck.value && hasXmlMapping.value
|
||||||
|
? '等待执行JSON一致性校验'
|
||||||
|
: '等待XML映射',
|
||||||
|
isSavingIcdCheckResult.value ? 'process' : canReachSaveStep.value ? 'process' : 'wait'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -139,10 +139,11 @@ const icdTypeOptions = [
|
|||||||
{ label: '手动录入的非标准', value: 2 },
|
{ label: '手动录入的非标准', value: 2 },
|
||||||
{ label: '上游解析传递', value: 3 }
|
{ label: '上游解析传递', value: 3 }
|
||||||
]
|
]
|
||||||
const formRules: FormRules<IcdPathFormModel> = {
|
const pathRequired = computed(() => !selectedIcdFile.value)
|
||||||
|
const formRules = computed<FormRules<IcdPathFormModel>>(() => ({
|
||||||
name: [{ required: true, message: '请输入 ICD 名称', trigger: 'blur' }],
|
name: [{ required: true, message: '请输入 ICD 名称', trigger: 'blur' }],
|
||||||
path: [{ required: true, message: '请输入 ICD 存储路径', trigger: 'blur' }]
|
path: pathRequired.value ? [{ required: true, message: '请输入 ICD 存储路径', trigger: 'blur' }] : []
|
||||||
}
|
}))
|
||||||
const dialogTitle = computed(() => (props.mode === 'create' ? '新增ICD记录' : '编辑ICD记录'))
|
const dialogTitle = computed(() => (props.mode === 'create' ? '新增ICD记录' : '编辑ICD记录'))
|
||||||
|
|
||||||
function unwrapApiPayload<T>(response: ResultData<T> | T): T {
|
function unwrapApiPayload<T>(response: ResultData<T> | T): T {
|
||||||
@@ -190,7 +191,7 @@ watch(
|
|||||||
|
|
||||||
const buildSavePayload = (): MmsMapping.CreateIcdPathRequest => ({
|
const buildSavePayload = (): MmsMapping.CreateIcdPathRequest => ({
|
||||||
name: formModel.name.trim(),
|
name: formModel.name.trim(),
|
||||||
path: formModel.path.trim(),
|
path: formModel.path.trim() || selectedIcdFile.value?.name || '',
|
||||||
angle: formModel.angle,
|
angle: formModel.angle,
|
||||||
usePhaseIndex: formModel.usePhaseIndex,
|
usePhaseIndex: formModel.usePhaseIndex,
|
||||||
type: formModel.type
|
type: formModel.type
|
||||||
@@ -202,6 +203,7 @@ const handleClose = () => {
|
|||||||
|
|
||||||
const handleIcdFileChange = (uploadFile: UploadFile) => {
|
const handleIcdFileChange = (uploadFile: UploadFile) => {
|
||||||
selectedIcdFile.value = uploadFile.raw || null
|
selectedIcdFile.value = uploadFile.raw || null
|
||||||
|
formRef.value?.clearValidate('path')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleIcdFileRemove = () => {
|
const handleIcdFileRemove = () => {
|
||||||
|
|||||||
@@ -29,7 +29,17 @@ const checks = [
|
|||||||
/<MappingConfirmDialog/.test(checkDialogSource)
|
/<MappingConfirmDialog/.test(checkDialogSource)
|
||||||
],
|
],
|
||||||
['flow still saves ICD check result through shared API', () => /saveIcdCheckResultApi/.test(flowSource)],
|
['flow still saves ICD check result through shared API', () => /saveIcdCheckResultApi/.test(flowSource)],
|
||||||
['flow supports saved callback for dialog host', () => /onIcdCheckSaved/.test(flowSource) && /options\.onIcdCheckSaved\?\.\(\)/.test(flowSource)]
|
['flow supports saved callback for dialog host', () => /onIcdCheckSaved/.test(flowSource) && /options\.onIcdCheckSaved\?\.\(\)/.test(flowSource)],
|
||||||
|
[
|
||||||
|
'ICD path check dialog only requires standard mapping when consistency check is visible',
|
||||||
|
() =>
|
||||||
|
/standardMappingJson:\s*computed\(\(\)\s*=>\s*\(?showConsistencyCheck\.value\s*\?\s*props\.activeIcdPathRecord\?\.jsonStr\?\.trim\(\)\s*\|\|\s*''\s*:\s*''\)?\)/.test(
|
||||||
|
checkDialogSource
|
||||||
|
) &&
|
||||||
|
/standardMappingName:\s*computed\(\(\)\s*=>\s*\(?showConsistencyCheck\.value\s*\?\s*props\.activeIcdPathRecord\?\.name\?\.trim\(\)\s*\|\|\s*''\s*:\s*''\)?\)/.test(
|
||||||
|
checkDialogSource
|
||||||
|
)
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
const failures = checks.filter(([, check]) => !check()).map(([name]) => name)
|
const failures = checks.filter(([, check]) => !check()).map(([name]) => name)
|
||||||
|
|||||||
@@ -78,7 +78,13 @@ const checks = [
|
|||||||
['ICD path type search uses select options', () => /prop:\s*'type'[\s\S]*enum:\s*icdTypeOptions[\s\S]*search:\s*\{[\s\S]*el:\s*'select'/.test(pageSource)],
|
['ICD path type search uses select options', () => /prop:\s*'type'[\s\S]*enum:\s*icdTypeOptions[\s\S]*search:\s*\{[\s\S]*el:\s*'select'/.test(pageSource)],
|
||||||
['ICD path form uses select for type', () => /<el-select\s+v-model="formModel\.type"[\s\S]*<el-option[\s\S]*v-for="option in icdTypeOptions"/.test(formDialogSource)],
|
['ICD path form uses select for type', () => /<el-select\s+v-model="formModel\.type"[\s\S]*<el-option[\s\S]*v-for="option in icdTypeOptions"/.test(formDialogSource)],
|
||||||
['new ICD path defaults to upstream parsed type', () => /type:\s*3/.test(formDialogSource) && /formModel\.type\s*=\s*3/.test(formDialogSource)],
|
['new ICD path defaults to upstream parsed type', () => /type:\s*3/.test(formDialogSource) && /formModel\.type\s*=\s*3/.test(formDialogSource)],
|
||||||
['ICD dialog action buttons match parse ICD primary style', () => isPrimarySolidButton(requestPanelSource, '选择 ICD') && isPrimarySolidButton(resultPanelSource, 'ICD校验') && isPrimarySolidButton(resultPanelSource, 'saveIcdCheckResultText')],
|
[
|
||||||
|
'ICD dialog action buttons match parse ICD primary style',
|
||||||
|
() =>
|
||||||
|
isPrimarySolidButton(requestPanelSource, '选择 ICD') &&
|
||||||
|
/<el-button[\s\S]*type="primary"[\s\S]*@click="emit\('icd-check'\)"/.test(resultPanelSource) &&
|
||||||
|
isPrimarySolidButton(resultPanelSource, 'saveIcdCheckResultText')
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'ICD table activation column calls activation handler before operation',
|
'ICD table activation column calls activation handler before operation',
|
||||||
() =>
|
() =>
|
||||||
@@ -87,17 +93,86 @@ const checks = [
|
|||||||
) && /renderActivationStatus[\s\S]*handleActivateIcdPath\(row\)/.test(pageSource)
|
) && /renderActivationStatus[\s\S]*handleActivateIcdPath\(row\)/.test(pageSource)
|
||||||
],
|
],
|
||||||
['ICD activation updates current record to standard type', () => /handleActivateIcdPath/.test(pageSource) && /type:\s*1/.test(pageSource) && /updateIcdPathApi/.test(pageSource)],
|
['ICD activation updates current record to standard type', () => /handleActivateIcdPath/.test(pageSource) && /type:\s*1/.test(pageSource) && /updateIcdPathApi/.test(pageSource)],
|
||||||
|
['ICD activation requires mapping JSON before setting standard type', () => /handleActivateIcdPath[\s\S]*row\.jsonStr\?\.trim\(\)[\s\S]*不能激活/.test(pageSource)],
|
||||||
|
['ICD page fetches active standard record independent of current table filters', () => /refreshActiveIcdPathRecord/.test(pageSource) && /listIcdPathsApi\(\{\s*type:\s*1\s*\}\)/.test(pageSource)],
|
||||||
['ICD path form supports multipart file save', () => /<el-upload[\s\S]*:auto-upload="false"[\s\S]*handleIcdFileChange/.test(formDialogSource) && /createIcdPathWithFileApi/.test(formDialogSource) && /updateIcdPathWithFileApi/.test(formDialogSource)],
|
['ICD path form supports multipart file save', () => /<el-upload[\s\S]*:auto-upload="false"[\s\S]*handleIcdFileChange/.test(formDialogSource) && /createIcdPathWithFileApi/.test(formDialogSource) && /updateIcdPathWithFileApi/.test(formDialogSource)],
|
||||||
|
['ICD path form allows uploaded file name to fill missing path', () => /pathRequired/.test(formDialogSource) && /selectedIcdFile\.value\?\.name/.test(formDialogSource)],
|
||||||
['ICD check dialog receives ICD type', () => /:icd-path-type="currentIcdCheckRecord\.type"/.test(pageSource) && /icdPathType:\s*number/.test(checkDialogSource)],
|
['ICD check dialog receives ICD type', () => /:icd-path-type="currentIcdCheckRecord\.type"/.test(pageSource) && /icdPathType:\s*number/.test(checkDialogSource)],
|
||||||
['ICD check dialog receives active record JSON as standard mapping', () => /:active-icd-path-record="activeIcdPathRecord"/.test(pageSource) && /activeIcdPathRecord:\s*MmsMapping\.IcdPathRecord\s*\|\s*null/.test(checkDialogSource) && /standardMappingJson/.test(flowSource)],
|
['ICD check dialog receives active record JSON as standard mapping', () => /:active-icd-path-record="activeIcdPathRecord"/.test(pageSource) && /activeIcdPathRecord:\s*MmsMapping\.IcdPathRecord\s*\|\s*null/.test(checkDialogSource) && /standardMappingJson/.test(flowSource)],
|
||||||
[
|
[
|
||||||
'standard and upstream ICD types show consistency check action',
|
'non-standard and upstream ICD types show consistency check action',
|
||||||
() =>
|
() =>
|
||||||
/showConsistencyCheck/.test(checkDialogSource) &&
|
/showConsistencyCheck/.test(checkDialogSource) &&
|
||||||
/props\.icdPathType\s*===\s*1[\s\S]*props\.icdPathType\s*===\s*3/.test(checkDialogSource) &&
|
/props\.icdPathType\s*===\s*2[\s\S]*props\.icdPathType\s*===\s*3/.test(checkDialogSource) &&
|
||||||
|
!/props\.icdPathType\s*===\s*1/.test(checkDialogSource) &&
|
||||||
/:show-icd-check-action="showConsistencyCheck"/.test(checkDialogSource)
|
/:show-icd-check-action="showConsistencyCheck"/.test(checkDialogSource)
|
||||||
],
|
],
|
||||||
['ICD check action calls backend consistency check before save', () => /@icd-check="handleIcdConsistencyCheck"/.test(checkDialogSource) && /handleIcdConsistencyCheck/.test(flowSource) && /checkIcdJsonConsistencyApi/.test(flowSource) && /lastIcdConsistencyCheckResult/.test(flowSource)],
|
['ICD check action calls backend consistency check before save', () => /@icd-check="handleIcdConsistencyCheck"/.test(checkDialogSource) && /handleIcdConsistencyCheck/.test(flowSource) && /checkIcdJsonConsistencyApi/.test(flowSource) && /lastIcdConsistencyCheckResult/.test(flowSource)],
|
||||||
|
[
|
||||||
|
'ICD check result renders success and failure status indicator',
|
||||||
|
() =>
|
||||||
|
/icdConsistencyStatus/.test(flowSource) &&
|
||||||
|
/:icd-consistency-status="icdConsistencyStatus"/.test(checkDialogSource) &&
|
||||||
|
/icd-consistency-indicator/.test(resultPanelSource) &&
|
||||||
|
/icdConsistencyProblemDialogVisible\s*=\s*true/.test(resultPanelSource)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'ICD check issues are separated from JSON mapping problems',
|
||||||
|
() =>
|
||||||
|
/const\s+jsonMappingProblemList\s*=\s*computed\(\(\)\s*=>\s*\[/.test(flowSource) &&
|
||||||
|
/const\s+icdConsistencyProblemList\s*=\s*computed\(\(\)\s*=>\s*lastIcdConsistencyCheckResult\.value\?\.issues/.test(
|
||||||
|
flowSource
|
||||||
|
) &&
|
||||||
|
!/const\s+problemList\s*=\s*computed\(\(\)\s*=>\s*\[[\s\S]*lastIcdConsistencyCheckResult\.value\?\.issues/.test(
|
||||||
|
flowSource
|
||||||
|
) &&
|
||||||
|
/:icd-consistency-problem-list="icdConsistencyProblemList"/.test(checkDialogSource) &&
|
||||||
|
/ICD_CONSISTENCY_PROBLEM_LABEL/.test(resultPanelSource)
|
||||||
|
],
|
||||||
|
['ICD check action uses JSON readiness instead of save readiness', () => /canRunIcdConsistencyCheck/.test(flowSource) && /:can-run-icd-consistency-check="canRunIcdConsistencyCheck"/.test(checkDialogSource) && /:disabled="!canRunIcdConsistencyCheck"/.test(resultPanelSource)],
|
||||||
|
[
|
||||||
|
'ICD check result save requires XML mapping before save',
|
||||||
|
() =>
|
||||||
|
/canSaveIcdCheckResult[\s\S]*xmlContentForExport\.value/.test(flowSource) &&
|
||||||
|
/handleSaveIcdCheckResult[\s\S]*xmlContentForExport\.value[\s\S]*请先完成 XML 映射后再保存/.test(flowSource) &&
|
||||||
|
/xml:\s*xmlContentForExport\.value/.test(flowSource)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'ICD check dialog keeps save after XML and optional consistency check',
|
||||||
|
() =>
|
||||||
|
/canReachSaveStep[\s\S]*showConsistencyCheck\.value\s*\?\s*hasIcdConsistencyCheckResult\.value\s*:\s*hasXmlMapping\.value/.test(
|
||||||
|
checkDialogSource
|
||||||
|
) &&
|
||||||
|
/steps\.push\([\s\S]*canReachSaveStep\.value[\s\S]*'可保存校验结果'[\s\S]*showConsistencyCheck\.value\s*&&\s*hasXmlMapping\.value[\s\S]*'等待执行JSON一致性校验'/.test(
|
||||||
|
checkDialogSource
|
||||||
|
)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'ICD path check msg uses JSON object payload and readable table render',
|
||||||
|
() =>
|
||||||
|
/interface\s+IcdCheckMsg[\s\S]*summary\?:\s*string[\s\S]*details\?:\s*string\[\][\s\S]*\[key:\s*string\]:\s*unknown/.test(
|
||||||
|
typeSource
|
||||||
|
) &&
|
||||||
|
/SaveIcdPathCheckResultRequest[\s\S]*msg\?:\s*IcdCheckMsg/.test(typeSource) &&
|
||||||
|
/IcdPathRecord[\s\S]*msg\?:\s*IcdCheckMsg\s*\|\s*string/.test(typeSource) &&
|
||||||
|
/buildIcdCheckMsg/.test(flowSource) &&
|
||||||
|
/summary:\s*summaryMessage/.test(flowSource) &&
|
||||||
|
/details:\s*checkResult\?\.issues/.test(flowSource) &&
|
||||||
|
/issuesJson:\s*checkResult\?\.issuesJson/.test(flowSource) &&
|
||||||
|
/correctedJson:\s*checkResult\?\.correctedJson/.test(flowSource) &&
|
||||||
|
/renderIcdCheckMsg/.test(pageSource) &&
|
||||||
|
/JSON\.stringify\(value\)/.test(pageSource)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'ICD path check save writes parsed ICD document back to path record',
|
||||||
|
() =>
|
||||||
|
/SaveIcdCheckResultRequest[\s\S]*icdDocument\?:\s*IcdDocument/.test(typeSource) &&
|
||||||
|
/SaveIcdPathCheckResultRequest[\s\S]*icdDocument\?:\s*IcdDocument/.test(typeSource) &&
|
||||||
|
/const\s+parsedIcdDocument\s*=\s*ref<MmsMapping\.IcdDocument\s*\|\s*null>\(null\)/.test(flowSource) &&
|
||||||
|
/parsedIcdDocument\.value\s*=\s*payload\.icdDocument\s*\|\|\s*null/.test(flowSource) &&
|
||||||
|
/icdDocument:\s*parsedIcdDocument\.value\s*\|\|\s*responsePayload\.value\?\.icdDocument/.test(flowSource)
|
||||||
|
],
|
||||||
|
['mapping result panel has no mojibake text', () => !/[鏄搴褰鍙纭鏍閰獙][\s\S]*[犲垪撳栨疆]/.test(resultPanelSource)],
|
||||||
['flow supports injected ICD check save handler', () => /saveIcdCheckResult\?:/.test(flowSource) && /options\.saveIcdCheckResult/.test(flowSource)],
|
['flow supports injected ICD check save handler', () => /saveIcdCheckResult\?:/.test(flowSource) && /options\.saveIcdCheckResult/.test(flowSource)],
|
||||||
['form dialog follows ICD check dialog visual shell', () => /class="icd-check-dialog"/.test(formDialogSource) && /class="icd-check-dialog__body"/.test(formDialogSource)],
|
['form dialog follows ICD check dialog visual shell', () => /class="icd-check-dialog"/.test(formDialogSource) && /class="icd-check-dialog__body"/.test(formDialogSource)],
|
||||||
['check dialog reuses shared MMS mapping flow panels', () => /<MappingRequestPanel/.test(checkDialogSource) && /<MappingConfigPanel/.test(checkDialogSource) && /<MappingResultPanel/.test(checkDialogSource) && /<MappingConfirmDialog/.test(checkDialogSource)]
|
['check dialog reuses shared MMS mapping flow panels', () => /<MappingRequestPanel/.test(checkDialogSource) && /<MappingConfigPanel/.test(checkDialogSource) && /<MappingResultPanel/.test(checkDialogSource) && /<MappingConfirmDialog/.test(checkDialogSource)]
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const currentDir = path.dirname(fileURLToPath(import.meta.url))
|
||||||
|
const rootDir = path.resolve(currentDir, '../../../..')
|
||||||
|
const panelFile = path.resolve(rootDir, 'views/tools/mmsMapping/components/MappingResultPanel.vue')
|
||||||
|
const source = fs.readFileSync(panelFile, 'utf8')
|
||||||
|
|
||||||
|
const checks = [
|
||||||
|
['JSON problem button uses dedicated JSON mapping issue text', () => /problemButtonText/.test(source)],
|
||||||
|
['Old generic problem dialog title is removed', () => !source.includes('title="问题列表"')],
|
||||||
|
['XML match result action opens dedicated XML match dialog', () => /@click="matchResultDialogVisible = true"/.test(source)],
|
||||||
|
['Old XML match result display text is removed', () => !source.includes('匹配结果展示')],
|
||||||
|
[
|
||||||
|
'ICD consistency status is placed in preview section, not panel actions',
|
||||||
|
() =>
|
||||||
|
/class="panel-section result-card grow-card preview-tab-section"[\s\S]*class="icd-consistency-status"/.test(
|
||||||
|
source
|
||||||
|
) &&
|
||||||
|
!/class="panel-actions"[\s\S]*class="icd-consistency-status"[\s\S]*<\/div>\s*<\/div>\s*<div class="panel-content/.test(
|
||||||
|
source
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
const failures = checks.filter(([, check]) => !check()).map(([name]) => name)
|
||||||
|
|
||||||
|
if (failures.length) {
|
||||||
|
console.error('mmsMapping result panel labels contract failed:')
|
||||||
|
for (const failure of failures) {
|
||||||
|
console.error(`- ${failure}`)
|
||||||
|
}
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('mmsMapping result panel labels contract passed')
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
import { Connection, Delete, Edit, Plus } from '@element-plus/icons-vue'
|
import { Connection, Delete, Edit, Plus } from '@element-plus/icons-vue'
|
||||||
import { ElMessage, ElMessageBox, type TagProps } from 'element-plus'
|
import { ElMessage, ElMessageBox, type TagProps } from 'element-plus'
|
||||||
import { reactive, ref } from 'vue'
|
import { nextTick, reactive, ref } from 'vue'
|
||||||
import type { ResultData } from '@/api/interface'
|
import type { ResultData } from '@/api/interface'
|
||||||
import ProTable from '@/components/ProTable/index.vue'
|
import ProTable from '@/components/ProTable/index.vue'
|
||||||
import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
|
import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
|
||||||
@@ -136,6 +136,18 @@ const icdTypeOptions = [
|
|||||||
|
|
||||||
const getIcdTypeText = (value?: number) => icdTypeOptions.find(option => option.value === value)?.label || '未知类型'
|
const getIcdTypeText = (value?: number) => icdTypeOptions.find(option => option.value === value)?.label || '未知类型'
|
||||||
|
|
||||||
|
const renderIcdCheckMsg = (value: MmsMapping.IcdPathRecord['msg']) => {
|
||||||
|
if (!value) return ''
|
||||||
|
if (typeof value === 'string') return value
|
||||||
|
if (typeof value.summary === 'string' && value.summary.trim()) return value.summary.trim()
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.stringify(value)
|
||||||
|
} catch {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const renderActivationStatus = (row: MmsMapping.IcdPathRecord) => {
|
const renderActivationStatus = (row: MmsMapping.IcdPathRecord) => {
|
||||||
if (row.type === 1) {
|
if (row.type === 1) {
|
||||||
return (
|
return (
|
||||||
@@ -225,7 +237,7 @@ const columns = reactive<ColumnProps<MmsMapping.IcdPathRecord>[]>([
|
|||||||
order: 3
|
order: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ prop: 'msg', label: '结论描述', minWidth: 220, isShow: false },
|
{ prop: 'msg', label: '结论描述', minWidth: 220, isShow: false, render: scope => renderIcdCheckMsg(scope.row.msg) },
|
||||||
{ prop: 'referenceIcdId', label: '标准ICD引用', minWidth: 170, isShow: false },
|
{ prop: 'referenceIcdId', label: '标准ICD引用', minWidth: 170, isShow: false },
|
||||||
{ prop: 'createTime', label: '创建时间', minWidth: 170 },
|
{ prop: 'createTime', label: '创建时间', minWidth: 170 },
|
||||||
{ prop: 'updateTime', label: '更新时间', minWidth: 170, isShow: false },
|
{ prop: 'updateTime', label: '更新时间', minWidth: 170, isShow: false },
|
||||||
@@ -255,7 +267,7 @@ const getTableList = async (params: IcdPathTableParams = {}) => {
|
|||||||
const pageSize = params.pageSize || 10
|
const pageSize = params.pageSize || 10
|
||||||
const startIndex = (pageNum - 1) * pageSize
|
const startIndex = (pageNum - 1) * pageSize
|
||||||
|
|
||||||
activeIcdPathRecord.value = records.find(record => record.type === 1 && record.state !== 0) || null
|
activeIcdPathRecord.value = records.find(record => record.type === 1 && record.state !== 0) || activeIcdPathRecord.value
|
||||||
|
|
||||||
// ICD 路径接口当前返回列表数据;这里统一包装为 ProTable 分页结构,保持和设备类型管理页一致。
|
// ICD 路径接口当前返回列表数据;这里统一包装为 ProTable 分页结构,保持和设备类型管理页一致。
|
||||||
return {
|
return {
|
||||||
@@ -268,9 +280,18 @@ const getTableList = async (params: IcdPathTableParams = {}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const refreshActiveIcdPathRecord = async () => {
|
||||||
|
// 关键业务节点:标准 ICD 不能依赖当前表格筛选结果,否则校验弹窗可能拿不到已激活记录的 JSON。
|
||||||
|
const response = await listIcdPathsApi({ type: 1 })
|
||||||
|
const records = unwrapApiPayload<MmsMapping.IcdPathRecord[]>(response) || []
|
||||||
|
|
||||||
|
activeIcdPathRecord.value = records.find(record => record.type === 1 && record.state !== 0) || null
|
||||||
|
}
|
||||||
|
|
||||||
const refreshIcdPaths = () => {
|
const refreshIcdPaths = () => {
|
||||||
proTable.value?.clearSelection()
|
proTable.value?.clearSelection()
|
||||||
proTable.value?.getTableList()
|
proTable.value?.getTableList()
|
||||||
|
refreshActiveIcdPathRecord()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleTableRequestError = (error: unknown) => {
|
const handleTableRequestError = (error: unknown) => {
|
||||||
@@ -333,6 +354,11 @@ const handleActivateIcdPath = async (row: MmsMapping.IcdPathRecord) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!row.jsonStr?.trim()) {
|
||||||
|
ElMessage.warning('当前 ICD 记录缺少 JSON 映射结果,不能激活,请先完成 ICD 校验并保存')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm('激活后该 ICD 将作为标准 ICD 参与一致性校验,是否继续?', '激活ICD记录', {
|
await ElMessageBox.confirm('激活后该 ICD 将作为标准 ICD 参与一致性校验,是否继续?', '激活ICD记录', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
@@ -381,8 +407,11 @@ const handleIcdCheck = (row: MmsMapping.IcdPathRecord) => {
|
|||||||
currentIcdCheckRecord.id = row.id
|
currentIcdCheckRecord.id = row.id
|
||||||
currentIcdCheckRecord.name = row.name || ''
|
currentIcdCheckRecord.name = row.name || ''
|
||||||
currentIcdCheckRecord.type = row.type ?? 3
|
currentIcdCheckRecord.type = row.type ?? 3
|
||||||
|
refreshActiveIcdPathRecord()
|
||||||
icdCheckDialogVisible.value = true
|
icdCheckDialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nextTick(refreshActiveIcdPathRecord)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { createBaseRequestPayload } from './requestPayload'
|
|||||||
type ResultTab = 'json' | 'xml' | 'problem'
|
type ResultTab = 'json' | 'xml' | 'problem'
|
||||||
type TagType = 'success' | 'warning' | 'info' | 'primary' | 'danger'
|
type TagType = 'success' | 'warning' | 'info' | 'primary' | 'danger'
|
||||||
type ExportMappingType = 'json' | 'xml'
|
type ExportMappingType = 'json' | 'xml'
|
||||||
|
type IcdConsistencyStatus = 'success' | 'failed' | ''
|
||||||
|
|
||||||
const DEFAULT_REQUEST_FORM: MmsMapping.BaseRequestForm = {
|
const DEFAULT_REQUEST_FORM: MmsMapping.BaseRequestForm = {
|
||||||
version: '1.0',
|
version: '1.0',
|
||||||
@@ -47,6 +48,7 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
const isGeneratingXml = ref(false)
|
const isGeneratingXml = ref(false)
|
||||||
const isSavingIcdCheckResult = ref(false)
|
const isSavingIcdCheckResult = ref(false)
|
||||||
const lastIcdConsistencyCheckResult = ref<MmsMapping.IcdJsonConsistencyCheckResponse | null>(null)
|
const lastIcdConsistencyCheckResult = ref<MmsMapping.IcdJsonConsistencyCheckResponse | null>(null)
|
||||||
|
const parsedIcdDocument = ref<MmsMapping.IcdDocument | null>(null)
|
||||||
const hasSequenceConfigured = ref(false)
|
const hasSequenceConfigured = ref(false)
|
||||||
const sequenceDialogVisible = ref(false)
|
const sequenceDialogVisible = ref(false)
|
||||||
const icdFileAccept = '.icd,.cid,.scd,.xml'
|
const icdFileAccept = '.icd,.cid,.scd,.xml'
|
||||||
@@ -253,7 +255,7 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
''
|
''
|
||||||
)
|
)
|
||||||
const canConfigureSequence = computed(() => Boolean(mappingJsonPreview.value && !isSubmitting.value))
|
const canConfigureSequence = computed(() => Boolean(mappingJsonPreview.value && !isSubmitting.value))
|
||||||
const canExportJsonMapping = computed(() => Boolean(xmlContentForExport.value && !isSubmitting.value))
|
const canExportJsonMapping = computed(() => Boolean(mappingJsonPreview.value && !isSubmitting.value))
|
||||||
const canExportXmlMapping = computed(() => Boolean(xmlContentForExport.value && !isSubmitting.value))
|
const canExportXmlMapping = computed(() => Boolean(xmlContentForExport.value && !isSubmitting.value))
|
||||||
const canGenerateXmlMapping = computed(() => Boolean(mappingJsonPreview.value && hasSequenceConfigured.value && !isSubmitting.value))
|
const canGenerateXmlMapping = computed(() => Boolean(mappingJsonPreview.value && hasSequenceConfigured.value && !isSubmitting.value))
|
||||||
const showXmlMappingTab = computed(() =>
|
const showXmlMappingTab = computed(() =>
|
||||||
@@ -263,10 +265,20 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
const standardMappingJson = computed(() => toValue(options.standardMappingJson)?.trim() || '')
|
const standardMappingJson = computed(() => toValue(options.standardMappingJson)?.trim() || '')
|
||||||
const standardMappingName = computed(() => toValue(options.standardMappingName)?.trim() || '已激活ICD记录')
|
const standardMappingName = computed(() => toValue(options.standardMappingName)?.trim() || '已激活ICD记录')
|
||||||
const showSaveIcdCheckResult = computed(() => Boolean(deviceTypeCheckId.value))
|
const showSaveIcdCheckResult = computed(() => Boolean(deviceTypeCheckId.value))
|
||||||
const canSaveIcdCheckResult = computed(() =>
|
const canRunIcdConsistencyCheck = computed(() =>
|
||||||
Boolean(deviceTypeCheckId.value && xmlContentForExport.value && !isSubmitting.value)
|
Boolean(mappingJsonPreview.value && standardMappingJson.value && !isSubmitting.value)
|
||||||
)
|
)
|
||||||
|
const canSaveIcdCheckResult = computed(() => {
|
||||||
|
if (!deviceTypeCheckId.value || !mappingJsonPreview.value || !xmlContentForExport.value || isSubmitting.value) return false
|
||||||
|
if (standardMappingJson.value && !lastIcdConsistencyCheckResult.value) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
const hasIcdConsistencyCheckResult = computed(() => Boolean(lastIcdConsistencyCheckResult.value))
|
const hasIcdConsistencyCheckResult = computed(() => Boolean(lastIcdConsistencyCheckResult.value))
|
||||||
|
const icdConsistencyStatus = computed<IcdConsistencyStatus>(() => {
|
||||||
|
if (!lastIcdConsistencyCheckResult.value) return ''
|
||||||
|
return lastIcdConsistencyCheckResult.value.result === 1 ? 'success' : 'failed'
|
||||||
|
})
|
||||||
const saveIcdCheckResultText = computed(() => '保存')
|
const saveIcdCheckResultText = computed(() => '保存')
|
||||||
|
|
||||||
const xmlMappingPreview = computed(() => {
|
const xmlMappingPreview = computed(() => {
|
||||||
@@ -307,11 +319,13 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
return '请先生成 JSON 映射'
|
return '请先生成 JSON 映射'
|
||||||
})
|
})
|
||||||
|
|
||||||
const problemList = computed(() => [
|
const jsonMappingProblemList = computed(() => [
|
||||||
...(responsePayload.value?.problems?.filter(Boolean) || []),
|
...(responsePayload.value?.problems?.filter(Boolean) || []),
|
||||||
...(xmlResponsePayload.value?.problems?.filter(Boolean) || []),
|
...(xmlResponsePayload.value?.problems?.filter(Boolean) || [])
|
||||||
...(lastIcdConsistencyCheckResult.value?.issues?.filter(Boolean) || [])
|
|
||||||
])
|
])
|
||||||
|
const problemList = jsonMappingProblemList
|
||||||
|
const icdConsistencyProblemList = computed(() => lastIcdConsistencyCheckResult.value?.issues?.filter(Boolean) || [])
|
||||||
|
const icdConsistencyProblemEmptyText = '当前 ICD 校验未返回 issues'
|
||||||
|
|
||||||
const methodDescribe = computed(() => xmlResponsePayload.value?.methodDescribe?.trim() || '')
|
const methodDescribe = computed(() => xmlResponsePayload.value?.methodDescribe?.trim() || '')
|
||||||
|
|
||||||
@@ -383,6 +397,7 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
responsePayload.value = null
|
responsePayload.value = null
|
||||||
xmlResponsePayload.value = null
|
xmlResponsePayload.value = null
|
||||||
lastIcdConsistencyCheckResult.value = null
|
lastIcdConsistencyCheckResult.value = null
|
||||||
|
parsedIcdDocument.value = null
|
||||||
hasSequenceConfigured.value = false
|
hasSequenceConfigured.value = false
|
||||||
sequenceDialogVisible.value = false
|
sequenceDialogVisible.value = false
|
||||||
parsedCandidates.value = []
|
parsedCandidates.value = []
|
||||||
@@ -418,6 +433,7 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
isParsing.value = true
|
isParsing.value = true
|
||||||
responsePayload.value = null
|
responsePayload.value = null
|
||||||
xmlResponsePayload.value = null
|
xmlResponsePayload.value = null
|
||||||
|
parsedIcdDocument.value = null
|
||||||
hasSequenceConfigured.value = false
|
hasSequenceConfigured.value = false
|
||||||
sequenceDialogVisible.value = false
|
sequenceDialogVisible.value = false
|
||||||
confirmDialogVisible.value = false
|
confirmDialogVisible.value = false
|
||||||
@@ -443,6 +459,8 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parsedCandidates.value = candidateGroups
|
parsedCandidates.value = candidateGroups
|
||||||
|
// 关键业务节点:保存 ICD 校验结果时,按后端调试文档回写解析后的 icdDocument 对象。
|
||||||
|
parsedIcdDocument.value = payload.icdDocument || null
|
||||||
|
|
||||||
// 关键业务节点:拿到 ICD 候选结果后必须先走 buildIndexConfirmData,生成人工确认弹窗所需模型。
|
// 关键业务节点:拿到 ICD 候选结果后必须先走 buildIndexConfirmData,生成人工确认弹窗所需模型。
|
||||||
const confirmResponse = await buildIndexConfirmDataApi(candidateGroups)
|
const confirmResponse = await buildIndexConfirmDataApi(candidateGroups)
|
||||||
@@ -649,6 +667,16 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const buildIcdCheckMsg = (
|
||||||
|
checkResult: MmsMapping.IcdJsonConsistencyCheckResponse | null,
|
||||||
|
summaryMessage: string
|
||||||
|
): MmsMapping.IcdCheckMsg => ({
|
||||||
|
summary: summaryMessage,
|
||||||
|
details: checkResult?.issues?.filter(Boolean) || [],
|
||||||
|
issuesJson: checkResult?.issuesJson || undefined,
|
||||||
|
correctedJson: checkResult?.correctedJson || undefined
|
||||||
|
})
|
||||||
|
|
||||||
const handleSaveIcdCheckResult = async () => {
|
const handleSaveIcdCheckResult = async () => {
|
||||||
if (!deviceTypeCheckId.value) {
|
if (!deviceTypeCheckId.value) {
|
||||||
ElMessage.warning('当前缺少设备类型 ID,不能入库校验结果')
|
ElMessage.warning('当前缺少设备类型 ID,不能入库校验结果')
|
||||||
@@ -657,7 +685,12 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
|
|
||||||
const mappingJson = responsePayload.value?.mappingJson?.trim() || mappingJsonPreview.value
|
const mappingJson = responsePayload.value?.mappingJson?.trim() || mappingJsonPreview.value
|
||||||
|
|
||||||
if (!mappingJson || !xmlContentForExport.value) {
|
if (!mappingJson) {
|
||||||
|
ElMessage.warning('请先生成 JSON 映射后再保存')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xmlContentForExport.value) {
|
||||||
ElMessage.warning('请先完成 XML 映射后再保存')
|
ElMessage.warning('请先完成 XML 映射后再保存')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -672,14 +705,15 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
try {
|
try {
|
||||||
const checkResult = lastIcdConsistencyCheckResult.value
|
const checkResult = lastIcdConsistencyCheckResult.value
|
||||||
const result = checkResult?.result ?? 1
|
const result = checkResult?.result ?? 1
|
||||||
const msg =
|
const summaryMessage =
|
||||||
checkResult?.message ||
|
checkResult?.message ||
|
||||||
(xmlContentForExport.value ? 'ICD一致性校验通过,JSON/XML已生成' : 'ICD一致性校验通过,JSON已生成')
|
(xmlContentForExport.value ? 'ICD一致性校验通过,JSON/XML已生成' : 'ICD一致性校验通过,JSON已生成')
|
||||||
const savePayload = {
|
const savePayload = {
|
||||||
|
icdDocument: parsedIcdDocument.value || responsePayload.value?.icdDocument,
|
||||||
mappingJson,
|
mappingJson,
|
||||||
xml: xmlContentForExport.value || undefined,
|
xml: xmlContentForExport.value,
|
||||||
result,
|
result,
|
||||||
msg
|
msg: buildIcdCheckMsg(checkResult, summaryMessage)
|
||||||
}
|
}
|
||||||
// 关键业务节点:ICD 校验流程可由设备类型或 ICD 存储记录承载,保存接口由宿主页注入以避免串写业务表。
|
// 关键业务节点:ICD 校验流程可由设备类型或 ICD 存储记录承载,保存接口由宿主页注入以避免串写业务表。
|
||||||
const response = options.saveIcdCheckResult
|
const response = options.saveIcdCheckResult
|
||||||
@@ -758,6 +792,8 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
problemTabLabel,
|
problemTabLabel,
|
||||||
problemList,
|
problemList,
|
||||||
problemEmptyText,
|
problemEmptyText,
|
||||||
|
icdConsistencyProblemList,
|
||||||
|
icdConsistencyProblemEmptyText,
|
||||||
methodDescribe,
|
methodDescribe,
|
||||||
canExportJsonMapping,
|
canExportJsonMapping,
|
||||||
canExportXmlMapping,
|
canExportXmlMapping,
|
||||||
@@ -767,10 +803,12 @@ export const useMmsMappingFlow = (options: UseMmsMappingFlowOptions = {}) => {
|
|||||||
showXmlMappingTab,
|
showXmlMappingTab,
|
||||||
sequenceDialogVisible,
|
sequenceDialogVisible,
|
||||||
showSaveIcdCheckResult,
|
showSaveIcdCheckResult,
|
||||||
|
canRunIcdConsistencyCheck,
|
||||||
canSaveIcdCheckResult,
|
canSaveIcdCheckResult,
|
||||||
isSavingIcdCheckResult,
|
isSavingIcdCheckResult,
|
||||||
saveIcdCheckResultText,
|
saveIcdCheckResultText,
|
||||||
hasIcdConsistencyCheckResult,
|
hasIcdConsistencyCheckResult,
|
||||||
|
icdConsistencyStatus,
|
||||||
confirmDialogVisible,
|
confirmDialogVisible,
|
||||||
isConfirmingSelection,
|
isConfirmingSelection,
|
||||||
handleIcdFileChange,
|
handleIcdFileChange,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="mapping-panel">
|
<section class="mapping-panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<div>
|
<div>
|
||||||
<div class="panel-title-tabs">
|
<div class="panel-title-tabs">
|
||||||
<span class="panel-title-tab">映射结果</span>
|
<span class="panel-title-tab">映射结果</span>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="showDescription" class="panel-description">展示和导出JSON与XML的映射结果,以及JSON的映射序列配置。</p>
|
<p v-if="showDescription" class="panel-description">Mapping result preview and sequence configuration.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-actions">
|
<div class="panel-actions">
|
||||||
<el-button
|
<el-button
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
v-if="showIcdCheckAction"
|
v-if="showIcdCheckAction"
|
||||||
type="primary"
|
type="primary"
|
||||||
:icon="CircleCheck"
|
:icon="CircleCheck"
|
||||||
:disabled="!canSaveIcdCheckResult"
|
:disabled="!canRunIcdConsistencyCheck"
|
||||||
@click="emit('icd-check')"
|
@click="emit('icd-check')"
|
||||||
>
|
>
|
||||||
ICD校验
|
ICD校验
|
||||||
@@ -52,6 +52,21 @@
|
|||||||
|
|
||||||
<div class="panel-content panel-content--fixed">
|
<div class="panel-content panel-content--fixed">
|
||||||
<div class="panel-section result-card grow-card preview-tab-section">
|
<div class="panel-section result-card grow-card preview-tab-section">
|
||||||
|
<div v-if="icdConsistencyStatus" class="icd-consistency-status">
|
||||||
|
<el-tooltip
|
||||||
|
:content="icdConsistencyStatus === 'success' ? 'ICD校验通过' : 'ICD校验不通过,点击查看JSON映射问题列表'"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
:class="['icd-consistency-indicator', `is-${icdConsistencyStatus}`]"
|
||||||
|
:disabled="icdConsistencyStatus !== 'failed'"
|
||||||
|
@click="openIcdConsistencyProblems"
|
||||||
|
>
|
||||||
|
<el-icon><WarningFilled /></el-icon>
|
||||||
|
</button>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
<div class="mapping-preview-tabs">
|
<div class="mapping-preview-tabs">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -87,6 +102,16 @@
|
|||||||
>
|
>
|
||||||
{{ problemButtonText }}
|
{{ problemButtonText }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="icdConsistencyStatus"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
size="small"
|
||||||
|
:icon="WarningFilled"
|
||||||
|
@click="icdConsistencyProblemDialogVisible = true"
|
||||||
|
>
|
||||||
|
{{ icdConsistencyProblemButtonText }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #trailing-actions>
|
<template #trailing-actions>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -118,7 +143,7 @@
|
|||||||
:disabled="!methodDescribe"
|
:disabled="!methodDescribe"
|
||||||
@click="matchResultDialogVisible = true"
|
@click="matchResultDialogVisible = true"
|
||||||
>
|
>
|
||||||
匹配结果展示
|
XML映射匹配结果列表
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -143,7 +168,7 @@
|
|||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="problemDialogVisible"
|
v-model="problemDialogVisible"
|
||||||
title="问题列表"
|
title="JSON映射问题列表"
|
||||||
width="720px"
|
width="720px"
|
||||||
destroy-on-close
|
destroy-on-close
|
||||||
top="8vh"
|
top="8vh"
|
||||||
@@ -158,7 +183,34 @@
|
|||||||
<el-empty v-else :description="problemEmptyText" />
|
<el-empty v-else :description="problemEmptyText" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog v-model="matchResultDialogVisible" title="匹配结果展示" width="640px" destroy-on-close top="12vh">
|
<el-dialog
|
||||||
|
v-model="icdConsistencyProblemDialogVisible"
|
||||||
|
:title="ICD_CONSISTENCY_PROBLEM_LABEL"
|
||||||
|
width="720px"
|
||||||
|
destroy-on-close
|
||||||
|
top="8vh"
|
||||||
|
class="mapping-problem-dialog"
|
||||||
|
>
|
||||||
|
<div v-if="icdConsistencyProblemList.length" class="problem-dialog-list">
|
||||||
|
<div
|
||||||
|
v-for="(problem, index) in icdConsistencyProblemList"
|
||||||
|
:key="`${index}-${problem}`"
|
||||||
|
class="problem-item"
|
||||||
|
>
|
||||||
|
<span class="problem-index">{{ index + 1 }}</span>
|
||||||
|
<span class="problem-text">{{ problem }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-empty v-else :description="icdConsistencyProblemEmptyText" />
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="matchResultDialogVisible"
|
||||||
|
title="XML映射匹配结果列表"
|
||||||
|
width="640px"
|
||||||
|
destroy-on-close
|
||||||
|
top="12vh"
|
||||||
|
>
|
||||||
<div class="match-result-detail">
|
<div class="match-result-detail">
|
||||||
{{ methodDescribe || '当前接口返回未包含 methodDescribe' }}
|
{{ methodDescribe || '当前接口返回未包含 methodDescribe' }}
|
||||||
</div>
|
</div>
|
||||||
@@ -178,7 +230,7 @@
|
|||||||
v-model="sequenceSearchKeyword"
|
v-model="sequenceSearchKeyword"
|
||||||
:prefix-icon="Search"
|
:prefix-icon="Search"
|
||||||
clearable
|
clearable
|
||||||
placeholder="按顶层、类型、上层描述、name 或路径检索"
|
placeholder="Search by top group, type, parent, name, or path"
|
||||||
/>
|
/>
|
||||||
<span class="dialog-search-count">
|
<span class="dialog-search-count">
|
||||||
{{ filteredSequenceRows.length }} / {{ sequenceConfigRows.length }}
|
{{ filteredSequenceRows.length }} / {{ sequenceConfigRows.length }}
|
||||||
@@ -192,7 +244,7 @@
|
|||||||
<h3 class="sequence-top-title">{{ group.topDesc || group.topKey }}</h3>
|
<h3 class="sequence-top-title">{{ group.topDesc || group.topKey }}</h3>
|
||||||
<p class="sequence-top-key">{{ group.topKey }}</p>
|
<p class="sequence-top-key">{{ group.topKey }}</p>
|
||||||
</div>
|
</div>
|
||||||
<el-tag type="info" effect="light">{{ group.rowCount }} 项</el-tag>
|
<el-tag type="info" effect="light">{{ group.rowCount }} items</el-tag>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sequence-type-list">
|
<div class="sequence-type-list">
|
||||||
@@ -204,7 +256,7 @@
|
|||||||
<div class="sequence-type-header">
|
<div class="sequence-type-header">
|
||||||
<div class="sequence-type-title">{{ typeGroup.typeName }}</div>
|
<div class="sequence-type-title">{{ typeGroup.typeName }}</div>
|
||||||
<el-tag type="primary" effect="plain" size="small">
|
<el-tag type="primary" effect="plain" size="small">
|
||||||
{{ typeGroup.rows.length }} 项
|
{{ typeGroup.rows.length }} items
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -232,9 +284,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<el-empty v-else description="当前检索条件下没有匹配的序列。" />
|
<el-empty v-else description="No sequence rows match the current search." />
|
||||||
</template>
|
</template>
|
||||||
<el-empty v-else description="当前 JSON 映射中未分析到包含 start 和 end 的序列。" />
|
<el-empty v-else description="No configurable sequence rows were found in the current JSON mapping." />
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="closeSequenceDialog">取消</el-button>
|
<el-button @click="closeSequenceDialog">取消</el-button>
|
||||||
<el-button type="primary" :disabled="!sequenceConfigRows.length" @click="confirmSequenceConfig">
|
<el-button type="primary" :disabled="!sequenceConfigRows.length" @click="confirmSequenceConfig">
|
||||||
@@ -246,7 +298,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { CircleCheck, Connection, Document, Download, Finished, Search, Setting, Warning } from '@element-plus/icons-vue'
|
import {
|
||||||
|
CircleCheck,
|
||||||
|
Connection,
|
||||||
|
Document,
|
||||||
|
Download,
|
||||||
|
Finished,
|
||||||
|
Search,
|
||||||
|
Setting,
|
||||||
|
Warning,
|
||||||
|
WarningFilled
|
||||||
|
} from '@element-plus/icons-vue'
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import JsonMappingTree from './JsonMappingTree.vue'
|
import JsonMappingTree from './JsonMappingTree.vue'
|
||||||
|
|
||||||
@@ -257,6 +319,7 @@ defineOptions({
|
|||||||
type TagType = 'success' | 'warning' | 'info' | 'primary' | 'danger'
|
type TagType = 'success' | 'warning' | 'info' | 'primary' | 'danger'
|
||||||
type ResultTab = 'json' | 'xml' | 'problem'
|
type ResultTab = 'json' | 'xml' | 'problem'
|
||||||
type ExportMappingType = 'json' | 'xml'
|
type ExportMappingType = 'json' | 'xml'
|
||||||
|
type IcdConsistencyStatus = 'success' | 'failed' | ''
|
||||||
type JsonObject = Record<string, unknown>
|
type JsonObject = Record<string, unknown>
|
||||||
type JsonPath = Array<string | number>
|
type JsonPath = Array<string | number>
|
||||||
|
|
||||||
@@ -302,6 +365,8 @@ const props = withDefaults(defineProps<{
|
|||||||
problemTabLabel: string
|
problemTabLabel: string
|
||||||
problemList: string[]
|
problemList: string[]
|
||||||
problemEmptyText: string
|
problemEmptyText: string
|
||||||
|
icdConsistencyProblemList: string[]
|
||||||
|
icdConsistencyProblemEmptyText: string
|
||||||
methodDescribe: string
|
methodDescribe: string
|
||||||
canExportJsonMapping: boolean
|
canExportJsonMapping: boolean
|
||||||
canExportXmlMapping: boolean
|
canExportXmlMapping: boolean
|
||||||
@@ -312,12 +377,15 @@ const props = withDefaults(defineProps<{
|
|||||||
sequenceDialogVisible: boolean
|
sequenceDialogVisible: boolean
|
||||||
showIcdCheckAction?: boolean
|
showIcdCheckAction?: boolean
|
||||||
showSaveIcdCheckResult: boolean
|
showSaveIcdCheckResult: boolean
|
||||||
|
canRunIcdConsistencyCheck: boolean
|
||||||
canSaveIcdCheckResult: boolean
|
canSaveIcdCheckResult: boolean
|
||||||
isSavingIcdCheckResult: boolean
|
isSavingIcdCheckResult: boolean
|
||||||
saveIcdCheckResultText: string
|
saveIcdCheckResultText: string
|
||||||
|
icdConsistencyStatus?: IcdConsistencyStatus
|
||||||
}>(), {
|
}>(), {
|
||||||
showDescription: true,
|
showDescription: true,
|
||||||
showIcdCheckAction: true
|
showIcdCheckAction: true,
|
||||||
|
icdConsistencyStatus: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -336,10 +404,18 @@ const activeTabProxy = computed({
|
|||||||
set: value => emit('update:activeResultTab', value)
|
set: value => emit('update:activeResultTab', value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const JSON_MAPPING_PROBLEM_LABEL = 'JSON\u6620\u5c04\u95ee\u9898\u5217\u8868'
|
||||||
|
const ICD_CONSISTENCY_PROBLEM_LABEL = 'ICD\u6821\u9a8c\u95ee\u9898\u5217\u8868'
|
||||||
const problemButtonText = computed(() =>
|
const problemButtonText = computed(() =>
|
||||||
props.problemList.length ? `问题列表(${props.problemList.length})` : '问题列表'
|
props.problemList.length ? `${JSON_MAPPING_PROBLEM_LABEL} (${props.problemList.length})` : JSON_MAPPING_PROBLEM_LABEL
|
||||||
|
)
|
||||||
|
const icdConsistencyProblemButtonText = computed(() =>
|
||||||
|
props.icdConsistencyProblemList.length
|
||||||
|
? `${ICD_CONSISTENCY_PROBLEM_LABEL} (${props.icdConsistencyProblemList.length})`
|
||||||
|
: ICD_CONSISTENCY_PROBLEM_LABEL
|
||||||
)
|
)
|
||||||
const problemDialogVisible = ref(false)
|
const problemDialogVisible = ref(false)
|
||||||
|
const icdConsistencyProblemDialogVisible = ref(false)
|
||||||
const matchResultDialogVisible = ref(false)
|
const matchResultDialogVisible = ref(false)
|
||||||
const sequenceConfigRows = ref<SequenceConfigRow[]>([])
|
const sequenceConfigRows = ref<SequenceConfigRow[]>([])
|
||||||
const sequenceSearchKeyword = ref('')
|
const sequenceSearchKeyword = ref('')
|
||||||
@@ -399,6 +475,11 @@ const sequenceConfigGroups = computed<SequenceConfigGroup[]>(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const openIcdConsistencyProblems = () => {
|
||||||
|
if (props.icdConsistencyStatus !== 'failed') return
|
||||||
|
icdConsistencyProblemDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
const isRecord = (value: unknown): value is JsonObject =>
|
const isRecord = (value: unknown): value is JsonObject =>
|
||||||
Boolean(value && typeof value === 'object' && !Array.isArray(value))
|
Boolean(value && typeof value === 'object' && !Array.isArray(value))
|
||||||
|
|
||||||
@@ -457,9 +538,9 @@ const collectSequenceRows = (
|
|||||||
pathText: getPathText(path),
|
pathText: getPathText(path),
|
||||||
topKey: getTopKey(path),
|
topKey: getTopKey(path),
|
||||||
topDesc: resolveTopDesc(rootSource, path),
|
topDesc: resolveTopDesc(rootSource, path),
|
||||||
parentDesc: parentDesc || '未配置上层描述',
|
parentDesc: parentDesc || 'Unconfigured parent',
|
||||||
desc: toDisplayText(source.desc, '未命名序列'),
|
desc: toDisplayText(source.desc, 'Unnamed sequence'),
|
||||||
name: toDisplayText(source.name, '未配置 name'),
|
name: toDisplayText(source.name, 'Unconfigured name'),
|
||||||
baseflag: toDisplayText(source.baseflag, ''),
|
baseflag: toDisplayText(source.baseflag, ''),
|
||||||
start: source.start === undefined || source.start === null ? '' : String(source.start),
|
start: source.start === undefined || source.start === null ? '' : String(source.start),
|
||||||
end: source.end === undefined || source.end === null ? '' : String(source.end),
|
end: source.end === undefined || source.end === null ? '' : String(source.end),
|
||||||
@@ -483,7 +564,7 @@ const normalizeSequenceValue = (value: string, valueType: string) => {
|
|||||||
|
|
||||||
const numericValue = Number(value)
|
const numericValue = Number(value)
|
||||||
if (!Number.isFinite(numericValue)) {
|
if (!Number.isFinite(numericValue)) {
|
||||||
throw new Error('start 和 end 需要填写有效数字')
|
throw new Error('start and end must be valid numbers')
|
||||||
}
|
}
|
||||||
|
|
||||||
return numericValue
|
return numericValue
|
||||||
@@ -497,7 +578,7 @@ const prepareSequenceDialog = () => {
|
|||||||
sequenceSearchKeyword.value = ''
|
sequenceSearchKeyword.value = ''
|
||||||
return true
|
return true
|
||||||
} catch {
|
} catch {
|
||||||
ElMessage.warning('当前 JSON 映射内容无法解析,不能配置序列')
|
ElMessage.warning('Current JSON mapping cannot be parsed for sequence configuration')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,6 +657,43 @@ const confirmSequenceConfig = () => {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icd-consistency-status {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 2;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icd-consistency-indicator {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: transparent;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icd-consistency-indicator.is-success {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icd-consistency-indicator.is-failed {
|
||||||
|
color: #e6a23c;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icd-consistency-indicator:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
.panel-title-tabs {
|
.panel-title-tabs {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -664,6 +782,7 @@ const confirmSequenceConfig = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.preview-tab-section {
|
.preview-tab-section {
|
||||||
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user