Appearance
属性编辑组件
组件在编辑器中使用时,需要提供一个该组件的属性编辑组件,命名规则为 【组件名】 + Attr。例如,组件名为 SVGWenBen,则其属性编辑组件名为 SVGWenBenAttr。该属性编辑组件仅在编辑状态下使用,运行状态不需要。如果组件不需要修改任何属性,可以提供一个空的属性编辑组件,或者不需要属性编辑组件也可以。该组件渲染在编辑器的右侧“属性”页签下的“组件属性”栏中,如图所示。
WARNING
组件的属性或数据配置通常都放在 propValue 对象中,并没有严格区分。组件定义者可根据需要自行划分在哪个编辑器中修改。

以SVGWenBenAttr为例
vue
<template>
<div class="attr-list">
<VECommonAttr :page-id="props.pageId">
<template #default>
<el-form :size="props.formSize" label-width="100px" label-position="left" style="padding:10px">
<el-form-item label="内容">
<el-input v-model="curComponent.propValue.text" type="text" class="common-item">
<template #append>
<el-icon
@click="copyText"><DocumentCopy /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item label="横向位移字符">
<el-input v-model="curComponent.propValue.dx" type="text" class="common-item"/>
</el-form-item>
<el-form-item label="x方向偏移量">
<el-input-number v-model="curComponent.propValue.offsetX" :precision="0" :step="1" :min="0" type="text" class="common-item"/>
</el-form-item>
<el-form-item label="边框背景">
<el-switch v-model="curComponent.propValue.hasBackground">
</el-switch>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="边框宽度">
<el-input-number v-model="curComponent.propValue.strokeWidth" :precision="0" :min="1" :max="10" type="text" class="common-item"/>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="边框圆角RX">
<el-input-number v-model="curComponent.propValue.rx" :precision="0" :min="0" :step="1" type="text" class="common-item"/>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="边框圆角RY">
<el-input-number v-model="curComponent.propValue.ry" :precision="0" :min="0" :step="1" type="text" class="common-item"/>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="边框颜色">
<div style="display: flex; gap: 10px; width: 100%;">
<el-color-picker v-model="curComponent.propValue.strokeColor" show-alpha
:predefine="predefine"></el-color-picker>
<el-button icon="DocumentCopy" style="width:30px;height:30px;"
@click="copyAttr(curComponent.propValue.strokeColor)">
</el-button>
</div>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="笔触透明度">
<el-input-number v-model="curComponent.propValue.strokeOpacity" :precision="1" :min="0" :step="0.1" :max="1" type="text" class="common-item"/>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="背景颜色">
<div style="display: flex; gap: 10px; width: 100%;">
<el-color-picker v-model="curComponent.propValue.fillColor" show-alpha
:predefine="predefine"></el-color-picker>
<el-button icon="DocumentCopy" style="width:30px;height:30px;"
@click="copyAttr(curComponent.propValue.fillColor)">
</el-button>
</div>
</el-form-item>
<el-form-item v-if="curComponent.propValue.hasBackground" label="填充透明度">
<el-input-number v-model="curComponent.propValue.fillOpacity" :precision="1" :min="0" :step="0.1" :max="1" type="text" class="common-item"/>
</el-form-item>
<el-form-item label="字体颜色">
<div style="display: flex; gap: 10px; width: 100%;">
<el-color-picker v-model="curComponent.propValue.fontColor" show-alpha
:predefine="predefine"></el-color-picker>
<el-button icon="DocumentCopy" style="width:30px;height:30px;"
@click="copyAttr(curComponent.propValue.fontColor)">
</el-button>
</div>
</el-form-item>
<el-form-item label="字体大小">
<el-input-number v-model="curComponent.propValue.fontSize" :precision="0" :min="2" :step="1" type="text" class="common-item"/>
</el-form-item>
<el-form-item label="字体粗细">
<el-select v-model="curComponent.propValue.fontWeight" placeholder="请选择" class="common-item">
<el-option
v-for="item in fontWeightArr"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="字体">
<el-select v-model="curComponent.propValue.fontFamily" placeholder="请选择" class="common-item">
<el-option
v-for="item in fontFamilyArr"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="水平对齐">
<el-select v-model="curComponent.propValue.horizontalAlign" placeholder="请选择" class="common-item">
<el-option
v-for="item in horizontalAlignArr"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-form>
</template>
</VECommonAttr>
</div>
</template>
<script setup>
import {useEditorStore} from "hflveditor3";
import {fontWeightArr, predefine,fontFamilyArr,horizontalAlignArr} from "@/custom-components/common/constant.js";
import {computed} from "vue";
import {copyAttr, copyToClipboard} from "@/custom-components/common/common.js";
import {showMessage} from "@/custom-components/common/message.js";
import { DocumentCopy } from '@element-plus/icons-vue';
const props = defineProps(['pageId','formSize'])
const editorStore = useEditorStore(props.pageId);
const curComponent = computed(() => {
return editorStore.curComponent
})
const propValue = computed(()=>{
return curComponent.value.propValue || {};
})
const copyText = ()=>{
let flag = copyToClipboard(propValue.value.text);
if (flag) {
showMessage("success","复制成功");
} else {
showMessage("error","复制失败");
}
}
</script>
<style lang="scss" scoped>
.attr-list {
.el-form {
padding:10px;
}
.el-form-item {
margin-bottom: 4px;
margin-right: 4px;
}
.common-item {
width: 180px;
}
.common-item :deep(.el-input-group__append) {
width: 24px;
height: 32px;
padding: 0 2px; /* 调整内边距 */
}
.picture-uploader {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 50px;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 14px;
color: #8c939d;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
}
.avatar {
width: 30px;
height: 30px;
display: block;
}
}
</style>TIP
VECommonAttr 是编辑器中提供的组件,即属性页签中的通用属性和通用样式等共性内容。
编辑器状态
通过编辑器的 Store 获取当前选中的组件对象。由于是多 Tab 编辑器模式,需要使用 useEditorStore 获取当前激活的 Tab 页签对应的编辑器。
javascript
import {useEditorStore} from "hflveditor3";
const props = defineProps(['pageId','formSize'])
const editorStore = useEditorStore(props.pageId);
const curComponent = computed(() => {
return editorStore.curComponent
})空属性编辑组件示例
如果组件不需要任何属性编辑,可以提供一个空的属性编辑组件,示例如下:
vue
<template>
<div class="attr-list">
<VECommonAttr :page-id="props.pageId" :form-size="props.formSize">
<template #default>
<el-form :size="props.formSize" label-width="100px" label-position="left" style="padding:10px">
</el-form>
</template>
</VECommonAttr>
</div>
</template>
<script setup>
import {computed} from "vue";
import {useEditorStore} from "hflveditor3";
const props = defineProps(['pageId','formSize'])
const editorStore = useEditorStore(props.pageId);
const curComponent = computed(() => {
return editorStore.curComponent
})
const propValue = computed(()=>{
return curComponent.value.propValue || {};
})
</script>
<style lang="scss" scoped>
.attr-list {
.el-form {
padding:10px;
}
.el-form-item {
margin-bottom: 4px;
margin-right: 4px;
}
.common-item {
width: 180px;
}
}
</style>组件注册
WARNING
示例中的属性编辑组件内部并没有包含注册命令的代码,这是因为通过统一安装时进行命名。开发者可根据自己的习惯选择在组件内部注册还是统一处理。
javascript
const svgComponents = ['SVGWenBen', 'SVGDataText']
svgComponents.forEach((key) => {
app.component(`${key}Attr`, defineAsyncComponent(() => import(`@/custom-components/svg/${key}/Attr.vue`)))
app.component(`${key}Data`, defineAsyncComponent(() => import(`@/custom-components/svg/${key}/Data.vue`)))
})