You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

135 lines
3.7 KiB

<script setup lang="ts">
import lodash from "lodash";
import { computed, reactive } from "vue";
import { ElCollapse, ElCollapseItem } from "element-plus";
import DataForm from "@/components/data-form/DataForm.vue";
import type { PropertyFlattenSetter, PropertySetterGroup } from "@/core/base/PropertyTypes.ts";
import type { DataFormProps } from "@/components/data-form/DataFormTypes.ts";
import { defDataFormProps } from "@/editor/widgets/property/PropertyPanelConstant.ts";
import Viewport, { type ViewportState } from "@/core/engine/Viewport.ts";
defineOptions({
name: 'PropertyPanel',
});
// 定义 Props 类型
interface PropertyPanelProps {
/** 待编辑数据 */
data?: any;
/** Viewport */
viewport: Viewport;
/** ViewportState */
viewportState: ViewportState;
/** 默认的DataFormProps */
defDataFormProps?: DataFormProps;
/** 最上面平铺的设置器 */
flatten?: PropertyFlattenSetter;
/** 设置器分组集合 */
groups?: Array<PropertySetterGroup>;
}
// 读取组件 props 属性
const props = withDefaults(defineProps<PropertyPanelProps>(), {});
// 定义 State 类型
interface PropertyPanelState {
/** 待编辑数据 */
data?: any;
/** 已展开的分组 */
expandGroups: Array<string>;
}
// state 属性
const state = reactive<PropertyPanelState>({
data: lodash.cloneDeep(props.data),
expandGroups: [],
});
// 定义 Data 类型
interface PropertyPanelData {
}
// 内部数据
const data: PropertyPanelData = {};
const flattenFormProps = computed(() => getDefFormProps(props.flatten));
function getDefFormProps(setter?: PropertyFlattenSetter) {
const formProps: DataFormProps = {
...defDataFormProps,
...props.defDataFormProps,
};
fillFormProps(setter);
return formProps;
}
function fillFormProps(formProps: DataFormProps, setter?: PropertyFlattenSetter) {
if (!setter) return;
if (setter.size) formProps.size = setter.size;
if (setter.labelWidth) formProps.labelWidth = setter.labelWidth;
}
function getCollapseItemId(group: PropertySetterGroup, idx: number) {
return `_${idx}_${group.title}`;
}
function onDataChange(newData: any) {
const viewport = props.viewport;
if (!viewport) return;
viewport.stateManager.beginStateUpdate();
lodash.merge(props.data, newData);
console.log("onDataChange", props.data === newData);
viewport.stateManager.endStateUpdate();
}
interface PropertyPanelExpose {
state: PropertyPanelState;
data: PropertyPanelData;
}
const expose: PropertyPanelExpose = {
state,
data,
};
// 定义组件公开内容
defineExpose(expose);
export type {
PropertyPanelProps,
PropertyPanelState,
}
</script>
<template>
<div class="property-panel">
<DataForm
v-if="props.flatten"
class="property-panel-form"
v-bind="flattenFormProps"
:data="state.data"
:formFields="props.flatten.fields"
@dataChange="onDataChange"
/>
<ElCollapse v-if="props.groups" v-model="state.expandGroups">
<ElCollapseItem
v-for="(group, idx) in props.groups"
:name="getCollapseItemId(group, idx)"
:title="group.title"
>
<DataForm
v-if="group"
class="property-panel-form"
v-bind="getDefFormProps(group)"
:data="state.data"
:formFields="props.flatten.fields"
@dataChange="onDataChange"
/>
</ElCollapseItem>
</ElCollapse>
</div>
</template>
<style scoped>
.property-panel {
padding: 8px 12px 16px 0;
}
</style>