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.
177 lines
6.1 KiB
177 lines
6.1 KiB
/**
|
|
* @name: RightAttributePanel
|
|
* @author: 卜启缘
|
|
* @date: 2021/4/28 16:59
|
|
* @description:属性编辑器
|
|
* @update: 2021/4/28 16:59
|
|
*/
|
|
import { defineComponent, PropType, reactive } from 'vue'
|
|
import styles from './index.module.scss'
|
|
import './index.common.scss'
|
|
import {
|
|
ElColorPicker,
|
|
ElForm,
|
|
ElFormItem,
|
|
ElInput,
|
|
ElInputNumber,
|
|
ElOption,
|
|
ElSelect,
|
|
ElSwitch,
|
|
ElTabPane,
|
|
ElTabs,
|
|
ElPopover
|
|
} from 'element-plus'
|
|
import { VisualEditorProps, VisualEditorPropsType } from '@/visual-editor/visual-editor.props'
|
|
import { TablePropEditor } from '@/visual-editor/components/right-attribute-panel/components/table-prop-editor/table-prop-editor'
|
|
import { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
|
import MonacoEditor from '../common/monaco-editor/MonacoEditor'
|
|
import { useVModel } from '@vueuse/core'
|
|
import { useDotProp } from '@/visual-editor/hooks/useDotProp'
|
|
import { useVisualData } from '@/visual-editor/hooks/useVisualData'
|
|
|
|
export default defineComponent({
|
|
name: 'RightAttributePanel',
|
|
props: {
|
|
block: { type: Object as PropType<VisualEditorBlockData>, default: () => ({}) }
|
|
},
|
|
setup(props, { emit }) {
|
|
const { visualConfig } = useVisualData()
|
|
|
|
const state = reactive({
|
|
activeName: 'attr',
|
|
isOpen: true,
|
|
editData: useVModel(props, 'block', emit)
|
|
})
|
|
|
|
const renderEditor = (propName: string, propConfig: VisualEditorProps) => {
|
|
const { propObj, prop } = useDotProp(state.editData.props, propName)
|
|
|
|
return {
|
|
[VisualEditorPropsType.input]: () => (
|
|
<ElInput v-model={propObj[prop]} placeholder={propConfig.tips || propConfig.label} />
|
|
),
|
|
[VisualEditorPropsType.inputNumber]: () => <ElInputNumber v-model={propObj[prop]} />,
|
|
[VisualEditorPropsType.switch]: () => <ElSwitch v-model={propObj[prop]} />,
|
|
[VisualEditorPropsType.color]: () => <ElColorPicker v-model={propObj[prop]} />,
|
|
[VisualEditorPropsType.select]: () => (
|
|
<ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}>
|
|
{(() => {
|
|
return propConfig.options!.map((opt) => (
|
|
<ElOption label={opt.label} value={opt.val} />
|
|
))
|
|
})()}
|
|
</ElSelect>
|
|
),
|
|
[VisualEditorPropsType.table]: () => (
|
|
<TablePropEditor v-model={propObj[prop]} propConfig={propConfig} />
|
|
)
|
|
}[propConfig.type]()
|
|
}
|
|
|
|
return () => {
|
|
const content: JSX.Element[] = []
|
|
|
|
if (!props.block) {
|
|
content.push(
|
|
<>
|
|
<ElFormItem label="容器宽度">
|
|
<ElInputNumber v-model={state.editData.width} {...({ step: 100 } as any)} />
|
|
</ElFormItem>
|
|
<ElFormItem label="容器高度">
|
|
<ElInputNumber v-model={state.editData.height} {...({ step: 100 } as any)} />
|
|
</ElFormItem>
|
|
</>
|
|
)
|
|
} else {
|
|
const { componentKey } = props.block
|
|
const component = visualConfig.componentMap[componentKey]
|
|
console.log('props.block:', props.block)
|
|
content.push(
|
|
<ElFormItem label="组件ID" labelWidth={'76px'}>
|
|
{props.block._vid}
|
|
<ElPopover
|
|
width={200}
|
|
trigger="hover"
|
|
content={`你可以利用该组件ID。对该组件进行获取和设置其属性,组件可用属性可在控制台输入:$$refs.${props.block._vid} 进行查看`}
|
|
v-slots={{
|
|
reference: () => (
|
|
<i style={{ marginLeft: '6px' }} class={'el-icon-warning-outline'}></i>
|
|
)
|
|
}}
|
|
></ElPopover>
|
|
</ElFormItem>
|
|
)
|
|
if (!!component) {
|
|
if (!!component.props) {
|
|
content.push(
|
|
<>
|
|
{Object.entries(component.props || {}).map(([propName, propConfig]) => (
|
|
<ElFormItem
|
|
key={propName}
|
|
v-slots={{
|
|
label: () =>
|
|
propConfig.tips ? (
|
|
<>
|
|
<ElPopover
|
|
width={200}
|
|
trigger={'hover'}
|
|
content={propConfig.tips}
|
|
v-slots={{
|
|
reference: () => <i class={'el-icon-warning-outline'}></i>
|
|
}}
|
|
></ElPopover>
|
|
{propConfig.label}
|
|
</>
|
|
) : (
|
|
propConfig.label
|
|
)
|
|
}}
|
|
>
|
|
{renderEditor(propName, propConfig)}
|
|
</ElFormItem>
|
|
))}
|
|
</>
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
const handleSchemaChange = (val) => {
|
|
try {
|
|
const newObj = JSON.parse(val)
|
|
Object.assign(state.editData, newObj)
|
|
} catch (e) {
|
|
console.log('JSON格式有误:', e)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div class={[styles.drawer, { [styles.isOpen]: state.isOpen }]}>
|
|
<div class={styles.floatingActionBtn} onClick={() => (state.isOpen = !state.isOpen)}>
|
|
<i class={`el-icon-d-arrow-${state.isOpen ? 'right' : 'left'}`}></i>
|
|
</div>
|
|
<div class={styles.attrs}>
|
|
<ElTabs v-model={state.activeName}>
|
|
<ElTabPane label="属性面板" name="attr">
|
|
<ElForm size="mini" label-position="left">
|
|
{content}
|
|
</ElForm>
|
|
</ElTabPane>
|
|
<ElTabPane label="JSON" name="json" lazy>
|
|
<MonacoEditor
|
|
code={JSON.stringify(props.block)}
|
|
layout={{ width: 300, height: 800 }}
|
|
vid={state.activeName == 'json' ? props.block._vid : -1}
|
|
onChange={handleSchemaChange}
|
|
title=""
|
|
/>
|
|
</ElTabPane>
|
|
</ElTabs>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
}
|
|
})
|
|
|