ConfigPanel.vue 5.12 KB
<template>
  <div class="config-panel-wrapper">
    <div class="config-panel-inner">
      <!-- 顶部按钮组 -->
      <div class="panel-actions-top">
        <VaButton color="primary" size="small" @click="$emit('save')">保存</VaButton>
        <VaButton color="secondary" size="small" @click="$emit('back')">返回</VaButton>
      </div>

      <h6 class="panel-title">元素配置</h6>

      <!-- 节点配置 -->
      <div v-if="selectedNode" class="config-form">
        <VaInput label="编码" :model-value="selectedNode.code" disabled readonly class="mb-3" />

        <VaSelect
          v-model="selectedNode.type"
          label="类型"
          :options="nodeTypeOptions"
          text-by="text"
          value-by="value"
          class="mb-3"
          @update:modelValue="$emit('sync')"
        />

        <VaInput v-model.number="selectedNode.x" label="坐标 X" type="number" class="mb-3" @change="$emit('sync')" />

        <VaInput v-model.number="selectedNode.y" label="坐标 Y" type="number" class="mb-3" @change="$emit('sync')" />

        <VaSelect
          v-model.number="selectedNode.orientation"
          label="朝向"
          :options="orientationOptions"
          text-by="text"
          value-by="value"
          class="mb-3"
          @update:modelValue="$emit('sync')"
        />

        <VaCheckbox
          v-model="selectedNode.allowRotate"
          label="是否允许旋转"
          class="mb-2"
          @update:modelValue="$emit('sync')"
        />

        <VaCheckbox v-model="selectedNode.allowReverseEntry" label="是否倒车进入" @update:modelValue="$emit('sync')" />
      </div>

      <!-- 连线配置 -->
      <div v-else-if="selectedEdge" class="config-form">
        <VaInput label="编码" :model-value="selectedEdge.code" disabled readonly class="mb-3" />

        <VaInput label="起始节点编号" :model-value="selectedEdge.sourceCode" disabled readonly class="mb-3" />

        <VaInput label="结束节点编号" :model-value="selectedEdge.targetCode" disabled readonly class="mb-3" />

        <VaCheckbox v-model="selectedEdge.isReverse" label="是否倒车" class="mb-2" @update:modelValue="$emit('sync')" />

        <VaCheckbox :model-value="!!selectedEdge.isArc" label="是否为弧线" disabled class="mb-2" />

        <VaInput
          label="圆心 X"
          :model-value="typeof selectedEdge.centerX === 'number' ? selectedEdge.centerX.toFixed(3) : ''"
          disabled
          readonly
          class="mb-3"
        />

        <VaInput
          label="圆心 Y"
          :model-value="typeof selectedEdge.centerY === 'number' ? selectedEdge.centerY.toFixed(3) : ''"
          disabled
          readonly
        />
      </div>

      <!-- 弧线配置 -->
      <div v-else-if="selectedArc" class="config-form">
        <VaInput label="编码" :model-value="selectedArc.code" disabled readonly class="mb-3" />

        <VaInput label="起始节点编号" :model-value="selectedArc.sourceCode" disabled readonly class="mb-3" />

        <VaInput label="结束节点编号" :model-value="selectedArc.targetCode" disabled readonly class="mb-3" />

        <VaCheckbox v-model="selectedArc.isReverse" label="是否倒车" class="mb-2" @update:modelValue="$emit('sync')" />

        <VaCheckbox :model-value="true" label="是否为弧线" disabled class="mb-2" />

        <VaInput
          label="圆心 X"
          :model-value="typeof selectedArc.centerX === 'number' ? selectedArc.centerX.toFixed(3) : ''"
          disabled
          readonly
          class="mb-3"
        />

        <VaInput
          label="圆心 Y"
          :model-value="typeof selectedArc.centerY === 'number' ? selectedArc.centerY.toFixed(3) : ''"
          disabled
          readonly
        />
      </div>

      <!-- 未选中提示 -->
      <div v-else class="text-secondary">请选择一个节点或一条连线以编辑属性。</div>
    </div>
  </div>
</template>

<script setup>
const nodeTypeOptions = [
  { text: '高速点', value: 'speediness' },
  { text: '充电点', value: 'charger' },
  { text: '储位', value: 'store' },
  { text: '停车位', value: 'parking' },
]

const orientationOptions = [
  { text: '无', value: null },
  { text: '0', value: 0 },
  { text: '90', value: 90 },
  { text: '180', value: 180 },
  { text: '270', value: -90 },
]

defineProps({
  selectedNode: Object,
  selectedEdge: Object,
  selectedArc: Object,
})

defineEmits(['save', 'back', 'sync'])
</script>

<style scoped>
.config-panel-wrapper {
  width: 15%;
  height: 100%;
  border-right: 1px solid var(--va-background-border);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.config-panel-inner {
  padding: 1rem;
  overflow-y: auto;
  height: 100%;
}

.panel-title {
  color: var(--va-primary);
  margin-bottom: 1rem;
  font-weight: 600;
}

.panel-actions-top {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--va-background-border);
}

.config-form {
  display: flex;
  flex-direction: column;
}

.mb-2 {
  margin-bottom: 0.5rem;
}

.mb-3 {
  margin-bottom: 1rem;
}

.text-secondary {
  color: var(--va-text-secondary);
  font-size: 0.875rem;
}
</style>