Files
CN_Tool_client/frontend/src/views/tools/mmsmapping/components/MappingConfigPanel.vue

220 lines
4.9 KiB
Vue
Raw Normal View History

2026-04-23 11:09:06 +08:00
<template>
<section class="mapping-panel config-panel">
<div class="panel-header">
<div>
<div class="panel-title-tabs">
<span class="panel-title-tab">索引配置</span>
</div>
<p v-if="showDescription" class="panel-description">展示现有的索引配置并允许继续编辑</p>
</div>
<div class="panel-actions">
<el-button
v-if="showConfirmButton"
type="primary"
:icon="EditPen"
:disabled="!canConfirm"
@click="emit('confirm-config')"
>
{{ confirmButtonText }}
</el-button>
<el-button
v-if="showGenerateButton"
type="primary"
:icon="Connection"
:loading="isGenerating"
:disabled="!canGenerate"
@click="emit('generate')"
>
JSON映射
</el-button>
2026-04-23 11:09:06 +08:00
</div>
</div>
<div class="panel-content">
<div class="panel-section result-card">
<el-alert v-if="jsonError" :title="jsonError" type="error" :closable="false" class="json-alert" />
<el-input
type="textarea"
class="index-selection-textarea"
:model-value="indexSelectionJson"
:disabled="isSubmitting"
:rows="18"
resize="none"
placeholder="索引配置完成后,这里会自动回填索引配置,仍可继续直接编辑。"
2026-04-23 11:09:06 +08:00
@update:model-value="value => emit('update:indexSelectionJson', String(value || ''))"
/>
</div>
<el-empty v-if="!hasDefaultJson" :description="emptyDescription" />
</div>
</section>
</template>
<script setup lang="ts">
import { Connection, EditPen } from '@element-plus/icons-vue'
2026-04-23 11:09:06 +08:00
defineOptions({
name: 'MappingConfigPanel'
})
withDefaults(defineProps<{
2026-04-23 11:09:06 +08:00
indexSelectionJson: string
isSubmitting: boolean
isGenerating: boolean
2026-04-23 11:09:06 +08:00
canGenerate: boolean
jsonError: string
showGenerateButton: boolean
showConfirmButton: boolean
confirmButtonText: string
canConfirm: boolean
2026-04-23 11:09:06 +08:00
hasDefaultJson: boolean
emptyDescription: string
showDescription?: boolean
}>(), {
showDescription: true
})
2026-04-23 11:09:06 +08:00
const emit = defineEmits<{
(event: 'update:indexSelectionJson', value: string): void
(event: 'confirm-config'): void
2026-04-23 11:09:06 +08:00
(event: 'generate'): void
}>()
</script>
<style scoped lang="scss">
.mapping-panel {
display: flex;
flex-direction: column;
gap: 16px;
min-height: 0;
padding: 24px;
border: 1px solid #e5e7eb;
border-radius: 12px;
background: #ffffff;
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
overflow: hidden;
}
.config-panel {
min-height: 0;
}
.panel-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
}
.panel-actions {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 12px;
white-space: nowrap;
}
.panel-actions :deep(.el-button + .el-button) {
margin-left: 0;
}
.panel-title-tabs {
display: inline-flex;
align-items: center;
border-bottom: 1px solid var(--el-border-color-light);
}
.panel-title-tab {
position: relative;
height: 36px;
padding: 0 2px;
font-size: 13px;
line-height: 36px;
color: var(--el-color-primary);
white-space: nowrap;
}
.panel-title-tab::after {
position: absolute;
right: 0;
bottom: -1px;
left: 0;
height: 2px;
background-color: var(--el-color-primary);
content: '';
2026-04-23 11:09:06 +08:00
}
.panel-description {
margin: 8px 0 0;
font-size: 14px;
line-height: 1.7;
color: #4b5563;
}
.panel-content {
display: flex;
flex: 1;
flex-direction: column;
gap: 16px;
min-height: 0;
overflow: hidden;
}
.panel-section {
border: none;
border-radius: 0;
background: transparent;
2026-04-23 11:09:06 +08:00
}
.result-card {
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
padding: 0;
2026-04-23 11:09:06 +08:00
overflow: hidden;
}
.index-selection-textarea {
flex: 1;
min-height: 0;
margin-top: 0;
}
.json-alert + .index-selection-textarea {
2026-04-23 11:09:06 +08:00
margin-top: 16px;
}
.index-selection-textarea :deep(.el-textarea) {
width: 100%;
height: 100%;
}
.index-selection-textarea :deep(.el-textarea__inner) {
height: 100%;
font-family: Consolas, 'Courier New', monospace;
line-height: 1.6;
overflow-y: auto;
}
.json-alert {
margin: 16px 0 0;
}
@media (max-width: 768px) {
.mapping-panel {
padding: 20px;
}
.panel-header {
flex-direction: column;
align-items: flex-start;
}
.panel-actions {
width: 100%;
}
2026-04-23 11:09:06 +08:00
}
</style>