refactor: simplified code

main
renqian805 2 years ago
parent 74df8be4f2
commit 035663eb3b
  1. 1
      components.d.ts
  2. 32
      package.json
  3. 511
      pnpm-lock.yaml
  4. 8
      src/packages/base-widgets/index.ts
  5. 2
      src/packages/base-widgets/text/fontArr.ts
  6. 2
      src/packages/base-widgets/text/index.tsx
  7. 4
      src/packages/container-component/index.ts
  8. 4
      src/packages/container-component/layout/index.tsx
  9. 4
      src/visual-editor/components/header/index.vue
  10. 37
      src/visual-editor/components/header/preview.vue
  11. 9
      src/visual-editor/components/left-aside/components/data-source/data-fetch.vue
  12. 14
      src/visual-editor/components/left-aside/components/data-source/utils.tsx
  13. 4
      src/visual-editor/components/left-aside/components/index.ts
  14. 8
      src/visual-editor/components/left-aside/index.vue
  15. 4
      src/visual-editor/components/right-attribute-panel/components/animate/Animate.tsx
  16. 20
      src/visual-editor/components/right-attribute-panel/components/animate/animateConfig.ts
  17. 2
      src/visual-editor/components/right-attribute-panel/components/attr-editor/components/table-prop-editor/table-prop-edit.service.tsx
  18. 72
      src/visual-editor/components/simulator-editor/draggable-transition-group.vue
  19. 330
      src/visual-editor/components/simulator-editor/simulator-editor.vue
  20. 77
      src/visual-editor/components/simulator-editor/slot-item.vue
  21. 2
      src/visual-editor/hooks/useModal.tsx
  22. 2
      src/visual-editor/utils/dialog-service.tsx
  23. 68
      src/visual-editor/visual-editor.utils.ts
  24. 8
      src/visual.config.tsx

1
components.d.ts vendored

@ -32,7 +32,6 @@ declare module '@vue/runtime-core' {
RouterLink: typeof import('vue-router')['RouterLink'];
RouterView: typeof import('vue-router')['RouterView'];
}
export interface ComponentCustomProperties {
vInfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'];
}

@ -33,13 +33,13 @@
"dependencies": {
"@element-plus/icons-vue": "^2.0.6",
"@vant/touch-emulator": "^1.3.2",
"@vueuse/core": "^8.7.5",
"@vueuse/integrations": "^8.7.5",
"@vueuse/core": "^8.9.1",
"@vueuse/integrations": "^8.9.1",
"animate.css": "^4.1.1",
"axios": "^0.27.2",
"dayjs": "^1.11.3",
"dexie": "^3.2.2",
"element-plus": "2.2.8",
"element-plus": "2.2.9",
"lodash-es": "^4.17.21",
"monaco-editor": "^0.33.0",
"nanoid": "^4.0.0",
@ -57,9 +57,9 @@
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@types/lodash-es": "^4.17.6",
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.30.3",
"@typescript-eslint/parser": "^5.30.3",
"@types/node": "^18.0.3",
"@typescript-eslint/eslint-plugin": "^5.30.5",
"@typescript-eslint/parser": "^5.30.5",
"@vitejs/plugin-legacy": "^1.8.2",
"@vitejs/plugin-vue": "^2.3.3",
"@vitejs/plugin-vue-jsx": "^1.3.10",
@ -71,32 +71,32 @@
"eslint-define-config": "^1.5.1",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.1.1",
"eslint-plugin-vue": "^9.2.0",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"lint-staged": "^12.5.0",
"postcss": "^8.4.14",
"postcss-html": "^1.4.1",
"postcss-html": "^1.5.0",
"postcss-scss": "^4.0.4",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3",
"rimraf": "^3.0.2",
"sass": "1.53.0",
"stylelint": "^14.9.1",
"stylelint-config-html": "^1.0.0",
"stylelint-config-html": "^1.1.0",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-recommended": "^8.0.0",
"stylelint-config-standard": "^26.0.0",
"stylelint-order": "^5.0.0",
"stylelint-scss": "^4.2.0",
"stylelint-scss": "^4.3.0",
"typescript": "^4.7.4",
"unplugin-auto-import": "^0.9.2",
"unplugin-vue-components": "^0.21.0",
"unplugin-vue-define-options": "^0.6.1",
"vite": "2.9.13",
"vite-plugin-checker": "^0.4.7",
"unplugin-vue-components": "^0.21.1",
"unplugin-vue-define-options": "^0.6.2",
"vite": "2.9.14",
"vite-plugin-checker": "^0.4.8",
"vite-plugin-windicss": "^1.8.6",
"vue-eslint-parser": "^9.0.3",
"vue-tsc": "^0.38.2",
"vue-tsc": "^0.38.3",
"windicss": "^3.5.6"
},
"repository": {

File diff suppressed because it is too large Load Diff

@ -1,10 +1,12 @@
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
const modules = import.meta.globEager('./*/index.tsx');
const components = {};
const components: Record<string, VisualEditorComponent> = {};
Object.keys(modules).forEach((key: string) => {
Object.entries(modules).forEach(([key, module]) => {
const name = key.replace(/\.\/(.*)\/index\.(tsx|vue)/, '$1');
components[name] = modules[key]?.default || modules[key];
components[name] = module?.default || module;
});
console.log(components, 'base-widgets');

@ -51,4 +51,4 @@ export const fontArr = [
{ label: '思源黑体', value: 'Source Han Sans CN' },
{ label: '思源宋体', value: 'Source Han Serif SC' },
{ label: '文泉驿微米黑', value: 'WenQuanYi Micro Hei' },
];
] as const;

@ -40,7 +40,7 @@ export default {
},
props: {
text: createEditorInputProp({ label: '显示文本' }),
font: createEditorSelectProp({ label: '字体设置', options: fontArr }),
font: createEditorSelectProp({ label: '字体设置', options: [...fontArr] }),
color: createEditorColorProp({ label: '字体颜色' }),
size: createEditorInputNumberProp({
label: '字体大小',

@ -1,6 +1,8 @@
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
const modules = import.meta.globEager('./*/index.tsx');
const components = {};
const components: Record<string, VisualEditorComponent> = {};
Object.keys(modules).forEach((key: string) => {
const name = key.replace(/\.\/(.*)\/index\.(tsx|vue)/, '$1');

@ -44,9 +44,9 @@ export default {
watchEffect(() => {
if (Object.keys(props.slots || {}).length) {
Object.keys(props.slots).forEach((key) => {
Object.entries<SlotItem>(props.slots).forEach(([key, slot]) => {
if (slotsTemp[block._vid][key]?.children) {
props.slots[key].children = slotsTemp[block._vid][key].children;
slot.children = slotsTemp[block._vid][key].children;
}
});
}

@ -74,6 +74,10 @@
import { useVisualData, localKey } from '@/visual-editor/hooks/useVisualData';
import { BASE_URL } from '@/visual-editor/utils';
defineOptions({
name: 'PageHeader',
});
const isShowH5Preview = ref(false);
const tools = useTools();

@ -10,37 +10,24 @@
</el-dialog>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue';
<script lang="ts" setup>
import { useVModel } from '@vueuse/core';
import { BASE_URL } from '@/visual-editor/utils';
/**
* @name: preview
* @author: 卜启缘
* @date: 2021/4/29 23:09
* @descriptionpreview
* @update: 2021/4/29 23:09
*/
export default defineComponent({
defineOptions({
name: 'Preview',
props: {
visible: {
type: Boolean,
default: false,
},
},
emits: ['update:visible'],
setup(props, { emit }) {
const state = reactive({
dialogVisible: useVModel(props, 'visible', emit),
previewUrl: `${BASE_URL}preview/${location.hash}`,
});
});
return {
...toRefs(state),
};
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(['update:visible']);
const dialogVisible = useVModel(props, 'visible', emits);
const previewUrl = `${BASE_URL}preview/${location.hash}`;
</script>
<style lang="scss">

@ -60,6 +60,7 @@
ElMessage,
ElCascader,
ElIcon,
ExpandTrigger,
} from 'element-plus';
import { cloneDeep } from 'lodash-es';
import { Delete, Edit } from '@element-plus/icons-vue';
@ -163,14 +164,14 @@
<ElFormItem label="请求数据" prop={'data.bind'}>
<ElCascader
v-model={state.ruleForm.data.bind}
options={models.value}
options={[...models.value]}
clearable={true}
props={{
checkStrictly: true,
children: 'entitys',
label: 'name',
value: 'key',
expandTrigger: 'hover',
expandTrigger: ExpandTrigger.HOVER,
}}
placeholder="请选择绑定的请求数据"
onChange={handleBindChange}
@ -184,12 +185,12 @@
children: 'entitys',
label: 'name',
value: 'key',
expandTrigger: 'hover',
expandTrigger: ExpandTrigger.HOVER,
}}
placeholder="请选择绑定的响应数据"
onChange={handleBindChange}
v-model={state.ruleForm.data.recv}
options={models.value}
options={[...models.value]}
></ElCascader>
</ElFormItem>
</ElForm>

@ -22,25 +22,25 @@ import { useModal } from '@/visual-editor/hooks/useModal';
export const importSwaggerJson = (swagger: any) => {
swagger = typeof swagger == 'string' ? JSON.parse(swagger) : swagger;
const models: VisualEditorModel[] = [];
Object.keys(swagger.definitions).forEach((model) => {
const properties = swagger.definitions[model].properties;
Object.entries<any>(swagger.definitions).forEach(([name, model]) => {
const properties = model.properties;
const modelItem: VisualEditorModel = {
name: model,
name,
key: generateNanoid(),
entitys: [],
};
Object.keys(properties).forEach((field) => {
Object.entries<any>(properties).forEach(([field, property]) => {
modelItem.entitys.push({
key: field,
name: properties[field].description || field,
type: properties[field].type,
name: property.description || field,
type: property.type,
value: '',
});
});
models.push(modelItem);
});
const apis: FetchApiItem[] = [];
Object.keys(swagger.paths).forEach((url) => {
Object.entries(swagger.paths).forEach(([url]) => {
Object.keys(swagger.paths[url]).forEach((method) => {
const apiUrlObj = swagger.paths[url][method];
const model = apiUrlObj.parameters?.[0]?.schema?.$ref?.split('/').pop();

@ -1,6 +1,8 @@
import { DefineComponent } from 'vue';
const modules = import.meta.globEager('./*/index.(tsx|vue)');
const components = {};
const components: Record<string, DefineComponent> = {};
console.log(modules, '起航');

@ -33,10 +33,10 @@
name: 'LeftAside',
});
const tabs = Object.keys(components)
.map((name) => {
const { label, icon, order } = components[name];
return { label, icon, name, order, comp: components[name] };
const tabs = Object.entries(components)
.map(([name, component]) => {
const { label, icon, order } = component;
return { label, icon, name, order, comp: component };
})
.sort((a, b) => a.order - b.order);

@ -142,10 +142,10 @@ export const Animate = defineComponent({
// 可添加的动画列表组件
const AnimateList = () => (
<ElTabs v-model={state.activeName} stretch>
{Object.keys(animationTabs).map((tabKey) => (
{Object.entries(animationTabs).map(([tabKey, animationBox]) => (
<ElTabPane label={animationTabs[tabKey].label} name={tabKey} key={tabKey}>
<ElRow gutter={10}>
{animationTabs[tabKey].value.map((animateItem: Animation) => (
{animationBox.value.map((animateItem: Animation) => (
<ElCol span={8} key={animateItem.value}>
<div
class={'animate-item'}

@ -1,17 +1,17 @@
import type { Animation } from '@/visual-editor/visual-editor.utils';
export interface animationBoxTs {
export type AnimationBox = {
label: string;
value: Animation[];
}
};
// 动画类型
export interface animationTabsTs {
in: animationBoxTs;
out: animationBoxTs;
other: animationBoxTs;
}
export type AnimationTabs = {
in: AnimationBox;
out: AnimationBox;
other: AnimationBox;
};
export const animationTabs: animationTabsTs = {
export const animationTabs: AnimationTabs = {
in: {
label: '进入',
value: [],
@ -431,7 +431,7 @@ const opt = [
},
],
},
];
] as const;
/**
* @return {Object} { animationValue: animatonLabel }
@ -446,7 +446,7 @@ const defaultOption = {
};
for (let index = 0; index < opt.length; index++) {
const items = opt[index].children;
items.forEach((item) => {
items.forEach((item: LabelValue) => {
if (inReg.test(item.label)) {
animationTabs.in.value.push({
...item,

@ -66,7 +66,7 @@ const ServiceComponent = defineComponent({
return () => (
<>
<ElDialog modelValue={state.showFlag}>
<ElDialog v-model={state.showFlag}>
{{
default: () => (
<div>

@ -22,7 +22,7 @@
</draggable>
</template>
<script lang="ts">
<script lang="ts" setup>
/**
* @name: draggable-transition-group
* @author:卜启缘
@ -30,52 +30,44 @@
* @descriptiondraggable-transition-group
* @update: 2021/5/1 23:15
*/
import { computed, defineComponent, reactive, toRefs, SetupContext } from 'vue';
import { computed } from 'vue';
import draggable from 'vuedraggable';
import { useVModel } from '@vueuse/core';
export default defineComponent({
defineOptions({
name: 'DraggableTransitionGroup',
components: { draggable },
props: {
moduleValue: {
type: Array,
default: () => [],
},
drag: {
type: Boolean,
default: false,
},
itemKey: {
type: String,
default: '_vid',
},
group: {
type: Object,
default: () => ({ name: 'components' }),
},
fallbackClass: String,
},
emits: ['update:moduleValue', 'update:drag'],
setup(props, { emit }: SetupContext) {
const state = reactive({
list: useVModel(props, 'moduleValue', emit),
isDrag: useVModel(props, 'drag', emit),
});
const dragOptions = computed(() => ({
animation: 200,
disabled: false,
scroll: true,
ghostClass: 'ghost',
}));
});
return {
...toRefs(state),
dragOptions,
};
const props = defineProps({
moduleValue: {
type: Array,
default: () => [],
},
drag: {
type: Boolean,
default: false,
},
itemKey: {
type: String,
default: '_vid',
},
group: {
type: Object,
default: () => ({ name: 'components' }),
},
fallbackClass: String,
});
const emit = defineEmits(['update:moduleValue', 'update:drag']);
const list = useVModel(props, 'moduleValue', emit);
const isDrag = useVModel(props, 'drag', emit);
const dragOptions = computed(() => ({
animation: 200,
disabled: false,
scroll: true,
ghostClass: 'ghost',
}));
</script>
<style lang="scss" scoped>

@ -53,8 +53,8 @@
</div>
</template>
<script lang="tsx">
import { defineComponent, reactive, watchEffect, toRefs } from 'vue';
<script lang="tsx" setup>
import { ref, watchEffect } from 'vue';
import { cloneDeep } from 'lodash-es';
import DraggableTransitionGroup from './draggable-transition-group.vue';
import CompRender from './comp-render';
@ -67,196 +67,176 @@
import { useModal } from '@/visual-editor/hooks/useModal';
import { generateNanoid } from '@/visual-editor/utils';
export default defineComponent({
defineOptions({
name: 'SimulatorEditor',
components: {
DraggableTransitionGroup,
CompRender,
SlotItem,
},
emits: ['on-selected'],
setup() {
const { currentPage, setCurrentBlock } = useVisualData();
});
const { globalProperties } = useGlobalProperties();
const { currentPage, setCurrentBlock } = useVisualData();
const state = reactive({
drag: false,
});
const { globalProperties } = useGlobalProperties();
const drag = ref(false);
/**
* @description 操作当前页面样式表
*/
watchEffect(() => {
const { bgImage, bgColor } = currentPage.value.config;
const bodyStyleStr = `
/**
* @description 操作当前页面样式表
*/
watchEffect(() => {
const { bgImage, bgColor } = currentPage.value.config;
const bodyStyleStr = `
.simulator-editor-content {
background-color: ${bgColor};
background-image: url(${bgImage});
}`;
const styleSheets = document.styleSheets[0];
const firstCssRule = document.styleSheets[0].cssRules[0];
const isExistContent = firstCssRule.cssText.includes('.simulator-editor-content');
if (isExistContent) {
styleSheets.deleteRule(0);
}
styleSheets.insertRule(bodyStyleStr);
});
const styleSheets = document.styleSheets[0];
const firstCssRule = document.styleSheets[0].cssRules[0];
const isExistContent = firstCssRule.cssText.includes('.simulator-editor-content');
if (isExistContent) {
styleSheets.deleteRule(0);
}
styleSheets.insertRule(bodyStyleStr);
});
//
//@leafId id
//@nodes Json
//@path 使
const findPathByLeafId = (
leafId,
nodes: VisualEditorBlockData[] = [],
path: VisualEditorBlockData[] = [],
) => {
for (let i = 0; i < nodes.length; i++) {
const tmpPath = path.concat();
tmpPath.push(nodes[i]);
if (leafId == nodes[i]._vid) {
return tmpPath;
}
const slots = nodes[i].props?.slots || {};
const keys = Object.keys(slots);
for (let j = 0; j < keys.length; j++) {
const children = slots[keys[j]]?.children;
if (children) {
const findResult = findPathByLeafId(leafId, children, tmpPath);
if (findResult) {
return findResult;
}
}
//
//@leafId id
//@nodes Json
//@path 使
const findPathByLeafId = (
leafId,
nodes: VisualEditorBlockData[] = [],
path: VisualEditorBlockData[] = [],
) => {
for (let i = 0; i < nodes.length; i++) {
const tmpPath = path.concat();
tmpPath.push(nodes[i]);
if (leafId == nodes[i]._vid) {
return tmpPath;
}
const slots = nodes[i].props?.slots || {};
const keys = Object.keys(slots);
for (let j = 0; j < keys.length; j++) {
const children = slots[keys[j]]?.children;
if (children) {
const findResult = findPathByLeafId(leafId, children, tmpPath);
if (findResult) {
return findResult;
}
}
};
//
const handleSlotsFocus = (block: VisualEditorBlockData, _vid: string) => {
const slots = block.props?.slots || {};
if (Object.keys(slots).length > 0) {
Object.keys(slots).forEach((key) => {
slots[key]?.children?.forEach((item) => {
item.focusWithChild = false;
item.focus = item._vid == _vid;
if (item.focus) {
const arr = findPathByLeafId(_vid, currentPage.value.blocks);
arr.forEach((n) => (n.focusWithChild = true));
}
if (Object.keys(item.props?.slots || {}).length) {
handleSlotsFocus(item, _vid);
}
});
});
}
};
}
}
};
//
const selectComp = (element: VisualEditorBlockData) => {
setCurrentBlock(element);
currentPage.value.blocks.forEach((block) => {
block.focus = element._vid == block._vid;
block.focusWithChild = false;
handleSlotsFocus(block, element._vid);
element.focusWithChild = false;
//
const handleSlotsFocus = (block: VisualEditorBlockData, _vid: string) => {
const slots = block.props?.slots || {};
if (Object.keys(slots).length > 0) {
Object.keys(slots).forEach((key) => {
slots[key]?.children?.forEach((item) => {
item.focusWithChild = false;
item.focus = item._vid == _vid;
if (item.focus) {
const arr = findPathByLeafId(_vid, currentPage.value.blocks);
arr.forEach((n) => (n.focusWithChild = true));
}
if (Object.keys(item.props?.slots || {}).length) {
handleSlotsFocus(item, _vid);
}
});
};
});
}
};
/**
* 删除组件
*/
const deleteComp = (
block: VisualEditorBlockData,
parentBlocks = currentPage.value.blocks,
) => {
console.log(block, 'block');
const index = parentBlocks.findIndex((item) => item._vid == block._vid);
if (index != -1) {
delete globalProperties.$$refs[parentBlocks[index]._vid];
const delTarget = parentBlocks.splice(index, 1)[0];
if (delTarget.focus) {
setCurrentBlock({} as VisualEditorBlockData);
}
}
};
//
const selectComp = (element: VisualEditorBlockData) => {
setCurrentBlock(element);
currentPage.value.blocks.forEach((block) => {
block.focus = element._vid == block._vid;
block.focusWithChild = false;
handleSlotsFocus(block, element._vid);
element.focusWithChild = false;
});
};
const onContextmenuBlock = (
e: MouseEvent,
block: VisualEditorBlockData,
parentBlocks = currentPage.value.blocks,
) => {
$$dropdown({
reference: e,
content: () => (
<>
<DropdownOption
label="复制节点"
icon="el-icon-document-copy"
{...{
onClick: () => {
const index = parentBlocks.findIndex((item) => item._vid == block._vid);
if (index != -1) {
const setBlockVid = (block: VisualEditorBlockData) => {
block._vid = `vid_${generateNanoid()}`;
block.focus = false;
const slots = block?.props?.slots || {};
const slotKeys = Object.keys(slots);
if (slotKeys.length) {
slotKeys.forEach((slotKey) => {
slots[slotKey]?.children?.forEach((child) => setBlockVid(child));
});
}
};
const blockCopy = cloneDeep(parentBlocks[index]);
setBlockVid(blockCopy);
parentBlocks.splice(index + 1, 0, blockCopy);
/**
* 删除组件
*/
const deleteComp = (block: VisualEditorBlockData, parentBlocks = currentPage.value.blocks) => {
console.log(block, 'block');
const index = parentBlocks.findIndex((item) => item._vid == block._vid);
if (index != -1) {
delete globalProperties.$$refs[parentBlocks[index]._vid];
const delTarget = parentBlocks.splice(index, 1)[0];
if (delTarget.focus) {
setCurrentBlock({} as VisualEditorBlockData);
}
}
};
const onContextmenuBlock = (
e: MouseEvent,
block: VisualEditorBlockData,
parentBlocks = currentPage.value.blocks,
) => {
$$dropdown({
reference: e,
content: () => (
<>
<DropdownOption
label="复制节点"
icon="el-icon-document-copy"
{...{
onClick: () => {
const index = parentBlocks.findIndex((item) => item._vid == block._vid);
if (index != -1) {
const setBlockVid = (block: VisualEditorBlockData) => {
block._vid = `vid_${generateNanoid()}`;
block.focus = false;
const slots = block?.props?.slots || {};
const slotKeys = Object.keys(slots);
if (slotKeys.length) {
slotKeys.forEach((slotKey) => {
slots[slotKey]?.children?.forEach((child) => setBlockVid(child));
});
}
};
const blockCopy = cloneDeep(parentBlocks[index]);
setBlockVid(blockCopy);
parentBlocks.splice(index + 1, 0, blockCopy);
}
},
}}
/>
<DropdownOption
label="查看节点"
icon="el-icon-view"
{...{
onClick: () =>
useModal({
title: '节点信息',
footer: null,
props: {
width: 600,
},
}}
/>
<DropdownOption
label="查看节点"
icon="el-icon-view"
{...{
onClick: () =>
useModal({
title: '节点信息',
footer: null,
props: {
width: 600,
},
content: () => (
<MonacoEditor
code={JSON.stringify(block)}
layout={{ width: 530, height: 600 }}
vid={block._vid}
/>
),
}),
}}
/>
<DropdownOption
label="删除节点"
icon="el-icon-delete"
{...{
onClick: () => deleteComp(block, parentBlocks),
}}
/>
</>
),
});
};
return {
...toRefs(state),
currentPage,
deleteComp,
selectComp,
onContextmenuBlock,
};
},
});
content: () => (
<MonacoEditor
code={JSON.stringify(block)}
layout={{ width: 530, height: 600 }}
vid={block._vid}
/>
),
}),
}}
/>
<DropdownOption
label="删除节点"
icon="el-icon-delete"
{...{
onClick: () => deleteComp(block, parentBlocks),
}}
/>
</>
),
});
};
</script>
<style lang="scss" scoped>
@import './func.scss';

@ -39,7 +39,7 @@
</draggable-transition-group>
</template>
<script lang="ts">
<script lang="ts" setup>
/**
* @name: slot-item
* @author:卜启缘
@ -48,54 +48,51 @@
* @update: 2021/5/2 22:36
*/
import { defineComponent, PropType } from 'vue';
import { PropType } from 'vue';
import { useVModel } from '@vueuse/core';
import DraggableTransitionGroup from './draggable-transition-group.vue';
import CompRender from './comp-render';
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils';
export default defineComponent({
defineOptions({
name: 'SlotItem',
components: { CompRender, DraggableTransitionGroup },
props: {
slotKey: {
type: String as PropType<string | number>,
default: '',
},
drag: {
type: Boolean as PropType<boolean>,
default: false,
},
children: {
type: Array as PropType<VisualEditorBlockData[]>,
default: () => [],
},
selectComp: {
type: Function as PropType<(comp: VisualEditorBlockData) => void>,
required: true,
},
onContextmenuBlock: {
type: Function as PropType<
(
e: MouseEvent,
block: VisualEditorBlockData,
parentBlocks?: VisualEditorBlockData[],
) => void
>,
required: true,
},
},
emits: ['update:children', 'on-selected', 'update:drag'],
setup(props, { emit }) {
//
props.children.some((item) => item.focus && props.selectComp(item));
});
return {
isDrag: useVModel(props, 'drag', emit),
slotChildren: useVModel(props, 'children', emit),
};
const props = defineProps({
slotKey: {
type: String as PropType<string | number>,
default: '',
},
drag: {
type: Boolean as PropType<boolean>,
default: false,
},
children: {
type: Array as PropType<VisualEditorBlockData[]>,
default: () => [],
},
selectComp: {
type: Function as PropType<(comp: VisualEditorBlockData) => void>,
required: true,
},
onContextmenuBlock: {
type: Function as PropType<
(
e: MouseEvent,
block: VisualEditorBlockData,
parentBlocks?: VisualEditorBlockData[],
) => void
>,
required: true,
},
});
const emit = defineEmits(['update:children', 'on-selected', 'update:drag']);
const isDrag = useVModel(props, 'drag', emit);
const slotChildren = useVModel(props, 'children', emit);
//
props.children.some((item) => item.focus && props.selectComp(item));
</script>
<style lang="scss" scoped>

@ -67,7 +67,7 @@ const Modal = defineComponent({
return () => (
<ElDialog
modelValue={state.visible}
v-model={state.visible}
title={state.options.title}
destroyOnClose={true}
{...state.options.props}

@ -64,7 +64,7 @@ const ServiceComponent = defineComponent({
return () => (
<>
<ElDialog modelValue={state.showFlag} title={state.option.title} key={state.key}>
<ElDialog v-model={state.showFlag} title={state.option.title} key={state.key}>
{{
default: () => (
<div>

@ -8,7 +8,7 @@ import { generateNanoid } from '@/visual-editor/utils';
/**
* @description
*/
export interface VisualEditorBlockData {
export type VisualEditorBlockData = {
/** 组件id 时间戳, 组件唯一标识 */
_vid: string;
/** 组件所属的模块(基础组件、容器组件) */
@ -42,11 +42,11 @@ export interface VisualEditorBlockData {
/** 组件事件集合 */
events: { label: string; value: string }[];
[prop: string]: any;
}
};
/**
* @description
*/
export interface ActionHandle {
export type ActionHandle = {
key: string;
name: string;
link: string[];
@ -54,32 +54,32 @@ export interface ActionHandle {
bind?: string;
recv?: string;
};
}
};
/**
* @description
*/
export interface Action {
export type Action = {
key: string;
name: string;
event: string;
handle: ActionHandle[];
}
};
/**
* @description
*/
export interface PageConfig {
export type PageConfig = {
/** 背景图片 */
bgImage: string;
/** 背景颜色 */
bgColor: string;
/** 是否缓存当前页面 */
keepAlive: boolean;
}
};
/**
* @description
*/
export interface VisualEditorPage {
export type VisualEditorPage = {
/** 页面标题 */
title: string;
/** 页面路径 */
@ -90,13 +90,13 @@ export interface VisualEditorPage {
config: PageConfig;
/** 当前页面的所有组件 */
blocks: VisualEditorBlockData[];
}
};
/**
* @description =>
*/
export interface VisualEditorPages {
export type VisualEditorPages = {
[path: string]: VisualEditorPage;
}
};
/**
* @description
*/
@ -114,18 +114,18 @@ export type EntityType = {
/**
* @description
*/
export interface VisualEditorModel {
export type VisualEditorModel = {
/** 数据源名称 */
name: string;
/** 绑定的字段 该字段创建的时候生成 */
key: string;
/** 实体集合 */
entitys: EntityType[];
}
};
/**
* @description
*/
export interface FetchApiItem {
export type FetchApiItem = {
/** 随机生成的key */
key: string;
/** 随机生成的key */
@ -144,12 +144,12 @@ export interface FetchApiItem {
/** 响应的结果绑定到某个实体上 */
recv: string;
};
}
};
/**
* @description
*/
export interface VisualEditorActions {
export type VisualEditorActions = {
fetch: {
name: '接口请求';
apis: FetchApiItem[];
@ -158,22 +158,22 @@ export interface VisualEditorActions {
name: '对话框';
handlers: [];
};
}
};
/**
* @description
*/
export interface VisualEditorModelValue {
export type VisualEditorModelValue = {
/** 页面 */
pages: VisualEditorPages;
/** 实体 */
models: VisualEditorModel[];
/** 动作 */
actions: VisualEditorActions;
}
};
/**
* @description
*/
export interface Animation {
export type Animation = {
/** 动画名称 */
label: string;
/** 动画类名 */
@ -186,11 +186,11 @@ export interface Animation {
count: number;
/** 是否无限循环动画 */
infinite: boolean;
}
};
/**
* @description
*/
export interface VisualEditorComponent {
export type VisualEditorComponent = {
/** 组件name */
key: string;
/** 组件所属模块名称 */
@ -221,12 +221,12 @@ export interface VisualEditorComponent {
events?: { label: string; value: string }[];
/** 组件样式 */
styles?: CSSProperties;
}
};
export interface VisualEditorMarkLines {
export type VisualEditorMarkLines = {
x: { left: number; showLeft: number }[];
y: { top: number; showTop: number }[];
}
};
export function createNewBlock(component: VisualEditorComponent): VisualEditorBlockData {
return {
@ -246,10 +246,10 @@ export function createNewBlock(component: VisualEditorComponent): VisualEditorBl
tempPadding: '0',
},
hasResize: false,
props: Object.keys(component.props || {}).reduce((prev, curr) => {
const { propObj, prop } = useDotProp(prev, curr);
if (component.props![curr]?.defaultValue) {
propObj[prop] = prev[curr] = component.props![curr]?.defaultValue;
props: Object.entries(component.props || {}).reduce((prev, [propName, propSchema]) => {
const { propObj, prop } = useDotProp(prev, propName);
if (propSchema?.defaultValue) {
propObj[prop] = prev[propName] = propSchema?.defaultValue;
}
return prev;
}, {}),
@ -262,7 +262,7 @@ export function createNewBlock(component: VisualEditorComponent): VisualEditorBl
};
}
export interface VisualDragEvent {
export type VisualDragEvent = {
dragstart: {
on: (cb: () => void) => void;
off: (cb: () => void) => void;
@ -273,7 +273,7 @@ export interface VisualDragEvent {
off: (cb: () => void) => void;
emit: () => void;
};
}
};
export const VisualDragProvider = (() => {
const VISUAL_DRAG_PROVIDER = '@@VISUAL_DRAG_PROVIDER';
@ -288,10 +288,10 @@ export const VisualDragProvider = (() => {
})();
// 组件模块
export interface ComponentModules {
export type ComponentModules = {
baseWidgets: VisualEditorComponent[]; // 基础组件
containerComponents: VisualEditorComponent[]; // 容器组件
}
};
/**
* @description
* @returns {}

@ -4,12 +4,12 @@ import containerComponent from '@/packages/container-component';
export const visualConfig = createVisualEditorConfig();
// 注册基础控件
Object.keys(baseWidgets).forEach((name: string) =>
visualConfig.registry('baseWidgets', name, baseWidgets[name]),
Object.entries(baseWidgets).forEach(([name, widget]) =>
visualConfig.registry('baseWidgets', name, widget),
);
// 注册容器组件
Object.keys(containerComponent).forEach((name: string) =>
visualConfig.registry('containerComponents', name, containerComponent[name]),
Object.entries(containerComponent).forEach(([name, widget]) =>
visualConfig.registry('containerComponents', name, widget),
);
console.log(

Loading…
Cancel
Save