Skip to content

PropertyDialog 属性对话框

用于编辑组件属性的对话框组件,常配合 PageDesigner 使用。

基础用法

最基础的属性对话框用法。

vue
<template>
  <NButton @click="show = true">编辑属性</NButton>
  <NPropertyDialog
    v-model="show"
    :componentMeta="componentMeta"
    :currentProps="currentProps"
    @update:currentProps="handleUpdate"
  />
</template>

<script setup>
import { ref } from 'vue')

const show = ref(false)
const currentProps = ref({
  text: '按钮',
  type: 'primary',
})

const componentMeta = {
  name: 'NButton',
  label: '按钮',
  icon: '🔘',
  description: '常用的操作按钮',
  props: [
    {
      name: 'text',
      label: '按钮文字',
      type: 'string',
      defaultValue: '按钮',
      group: '基础',
    },
    {
      name: 'type',
      label: '按钮类型',
      type: 'select',
      options: [
        { label: '默认', value: '' },
        { label: '主要', value: 'primary' },
        { label: '成功', value: 'success' },
        { label: '警告', value: 'warning' },
        { label: '危险', value: 'danger' },
      ],
      defaultValue: '',
      group: '基础',
    },
  ],
}

const handleUpdate = (newProps) => {
  currentProps.value = newProps
  console.log('属性更新:', newProps)
}
</script>

分组显示

属性会按照 group 字段自动分组显示。

vue
<template>
  <NButton @click="show = true">编辑属性</NButton>
  <NPropertyDialog
    v-model="show"
    :componentMeta="componentMeta"
    :currentProps="currentProps"
    @update:currentProps="handleUpdate"
  />
</template>

<script setup>
import { ref } from 'vue')

const show = ref(false)
const currentProps = ref({
  text: '按钮',
  type: 'primary',
  size: 'default',
  disabled: false,
})

const componentMeta = {
  name: 'NButton',
  label: '按钮',
  icon: '🔘',
  description: '常用的操作按钮',
  props: [
    {
      name: 'text',
      label: '按钮文字',
      type: 'string',
      defaultValue: '按钮',
      group: '基础',
    },
    {
      name: 'type',
      label: '按钮类型',
      type: 'select',
      options: [
        { label: '默认', value: '' },
        { label: '主要', value: 'primary' },
        { label: '成功', value: 'success' },
        { label: '警告', value: 'warning' },
        { label: '危险', value: 'danger' },
      ],
      defaultValue: '',
      group: '基础',
    },
    {
      name: 'size',
      label: '尺寸',
      type: 'select',
      options: [
        { label: '大型', value: 'large' },
        { label: '默认', value: 'default' },
        { label: '小型', value: 'small' },
      ],
      defaultValue: 'default',
      group: '样式',
    },
    {
      name: 'disabled',
      label: '禁用',
      type: 'boolean',
      defaultValue: false,
      group: '状态',
    },
  ],
}

const handleUpdate = (newProps) => {
  currentProps.value = newProps
  console.log('属性更新:', newProps)
}
</script>

重置默认值

点击"重置默认值"按钮可以将所有属性重置为默认值。

vue
<template>
  <NButton @click="show = true">编辑属性</NButton>
  <NPropertyDialog
    v-model="show"
    :componentMeta="componentMeta"
    :currentProps="currentProps"
    @update:currentProps="handleUpdate"
    @reset="handleReset"
  />
</template>

<script setup>
import { ref } from 'vue')

const show = ref(false)
const currentProps = ref({
  text: '按钮',
  type: 'primary',
})

const componentMeta = {
  name: 'NButton',
  label: '按钮',
  icon: '🔘',
  props: [
    {
      name: 'text',
      label: '按钮文字',
      type: 'string',
      defaultValue: '按钮',
    },
    {
      name: 'type',
      label: '按钮类型',
      type: 'select',
      options: [
        { label: '默认', value: '' },
        { label: '主要', value: 'primary' },
      ],
      defaultValue: '',
    },
  ],
}

const handleUpdate = (newProps) => {
  currentProps.value = newProps
}

const handleReset = () => {
  console.log('已重置为默认值')
}
</script>

无属性状态

当组件没有可编辑属性时,会显示空状态。

vue
<template>
  <NButton @click="show = true">编辑属性</NButton>
  <NPropertyDialog
    v-model="show"
    :componentMeta="componentMeta"
    :currentProps="currentProps"
  />
</template>

<script setup>
import { ref } from 'vue')

const show = ref(false)
const currentProps = ref({})

const componentMeta = {
  name: 'NIcon',
  label: '图标',
  icon: '🎨',
  description: '图标组件',
  props: [],
}
</script>

空组件元数据

当组件元数据为 null 时,会显示默认状态。

vue
<template>
  <NButton @click="show = true">编辑属性</NButton>
  <NPropertyDialog
    v-model="show"
    :componentMeta="null"
    :currentProps="{}"
  />
</template>

<script setup>
import { ref } from 'vue')

const show = ref(false)
</script>

配合 PageDesigner 使用

在 PageDesigner 中选中组件后,打开属性对话框进行编辑。

vue
<template>
  <NPageDesigner
    :schema="schema"
    @select="handleSelect"
  />
  <NPropertyDialog
    v-model="showDialog"
    :componentMeta="selectedMeta"
    :currentProps="selectedProps"
    @update:currentProps="handleUpdateProps"
  />
</template>

<script setup>
import { ref } from 'vue')

const schema = ref({
  components: [
    {
      id: '1',
      type: 'button',
      props: { text: '按钮', type: 'primary' },
      position: { x: 100, y: 100, width: 120, height: 40 },
    },
  ],
  dataFlow: [],
})

const showDialog = ref(false)
const selectedMeta = ref(null)
const selectedProps = ref({})

// 组件元数据映射
const componentMetaMap = {
  button: {
    name: 'NButton',
    label: '按钮',
    icon: '🔘',
    props: [
      {
        name: 'text',
        label: '按钮文字',
        type: 'string',
        defaultValue: '按钮',
        group: '基础',
      },
      {
        name: 'type',
        label: '按钮类型',
        type: 'select',
        options: [
          { label: '默认', value: '' },
          { label: '主要', value: 'primary' },
        ],
        defaultValue: '',
        group: '基础',
      },
    ],
  },
}

const handleSelect = (component) => {
  selectedMeta.value = componentMetaMap[component.type] || null
  selectedProps.value = { ...component.props }
  showDialog.value = true
}

const handleUpdateProps = (newProps) => {
  selectedProps.value = newProps
  // 更新 schema 中对应组件的 props
  const component = schema.value.components.find(
    (c) => c.id === selectedMeta.value?.name
  )
  if (component) {
    component.props = newProps
  }
}
</script>

自定义表单项类型

支持多种表单项类型:stringnumberbooleanselectcolordate 等。

vue
<template>
  <NButton @click="show = true">编辑属性</NButton>
  <NPropertyDialog
    v-model="show"
    :componentMeta="componentMeta"
    :currentProps="currentProps"
    @update:currentProps="handleUpdate"
  />
</template>

<script setup>
import { ref } from 'vue')

const show = ref(false)
const currentProps = ref({
  title: '标题',
  count: 10,
  visible: true,
  theme: 'light',
  color: '#1890ff',
  date: '2024-01-01',
})

const componentMeta = {
  name: 'NExample',
  label: '示例组件',
  icon: '📦',
  props: [
    {
      name: 'title',
      label: '标题',
      type: 'string',
      defaultValue: '标题',
      group: '基础',
    },
    {
      name: 'count',
      label: '数量',
      type: 'number',
      defaultValue: 10,
      group: '基础',
    },
    {
      name: 'visible',
      label: '是否可见',
      type: 'boolean',
      defaultValue: true,
      group: '状态',
    },
    {
      name: 'theme',
      label: '主题',
      type: 'select',
      options: [
        { label: '浅色', value: 'light' },
        { label: '深色', value: 'dark' },
      ],
      defaultValue: 'light',
      group: '样式',
    },
    {
      name: 'color',
      label: '颜色',
      type: 'color',
      defaultValue: '#1890ff',
      group: '样式',
    },
    {
      name: 'date',
      label: '日期',
      type: 'date',
      defaultValue: '2024-01-01',
      group: '其他',
    },
  ],
}

const handleUpdate = (newProps) => {
  currentProps.value = newProps
  console.log('属性更新:', newProps)
}
</script>

API

Props

属性说明类型默认值
modelValue是否显示弹窗booleanfalse
componentMeta组件元数据ComponentMeta | nullnull
currentProps当前 props 值Record<string, any>{}

ComponentMeta

属性说明类型
name组件名称string
label组件标签string
icon组件图标string
description组件描述string
props属性列表PropMeta[]

PropMeta

属性说明类型
name属性名称string
label属性标签string
type属性类型'string' | 'number' | 'boolean' | 'select' | 'color' | 'date'
defaultValue默认值any
options选项(type 为 select 时){ label: string; value: any }[]
group分组名称string

Events

事件名说明类型
update:modelValue显示状态改变时触发(value: boolean) => void
update:currentProps属性值改变时触发(value: Record<string, any>) => void
reset点击重置按钮时触发() => void

Slots

插槽名说明
header自定义头部内容
footer自定义底部内容