add:完善组件删除功能
This commit is contained in:
3
auto-imports.d.ts
vendored
3
auto-imports.d.ts
vendored
@ -3,6 +3,7 @@
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
@ -303,6 +304,6 @@ declare global {
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
</VueDraggable>
|
||||
</div>
|
||||
<div class="right">
|
||||
<PropertyEditor :scheme="store.nowComponentsData"></PropertyEditor>
|
||||
<PropertyEditor v-if="store.nowComponentsData" :scheme="store.nowComponentsData"></PropertyEditor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -76,9 +76,9 @@ import axios from 'axios';
|
||||
let componentsList = [];
|
||||
const store = useSchemeStore();
|
||||
|
||||
// watch(store, (n) => {
|
||||
// console.log("store发生了变化", n);
|
||||
// });
|
||||
watch(store, (n) => {
|
||||
console.log("store发生了变化", n);
|
||||
});
|
||||
|
||||
const baseScheme = {
|
||||
"type": "AdaptivePage",
|
||||
@ -157,24 +157,24 @@ function clone(element: Record<'name' | 'id' | 'type' | 'props' | 'class' | 'tex
|
||||
}
|
||||
|
||||
const onEnd = (event: DraggableEvent) => {
|
||||
console.log("onEnd", event);
|
||||
// console.log("onEnd", event);
|
||||
store.nowComponentsData = event.clonedData;
|
||||
};
|
||||
|
||||
const onStart = (event) => {
|
||||
console.log("onStart", event);
|
||||
// console.log("onStart", event);
|
||||
};
|
||||
|
||||
const onPreviewStart = (event) => {
|
||||
console.log("onPreviewStart", event);
|
||||
// console.log("onPreviewStart", event);
|
||||
};
|
||||
|
||||
const onPreviewUpdate = (event) => {
|
||||
console.log("onPreviewUpdate", event);
|
||||
// console.log("onPreviewUpdate", event);
|
||||
};
|
||||
|
||||
const onPreviewStop = (event) => {
|
||||
console.log(event);
|
||||
// console.log(event);
|
||||
};
|
||||
|
||||
const save = async () => {
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<div
|
||||
style="width: fit-content; display: flex; flex-direction: column; position: relative;"
|
||||
v-if="componentVisible || store.designerMode"
|
||||
v-if="store.nowComponentsData!==null&&(componentVisible || store.designerMode)"
|
||||
:id="componentId"
|
||||
:class="[
|
||||
'dynamic-component',
|
||||
{ 'hover-state': isHovered },
|
||||
{ 'click-state': isClicked }
|
||||
{ 'click-state': componentSelected }
|
||||
]"
|
||||
@click.stop="handleClick"
|
||||
@mouseover="isHovered = true"
|
||||
@mouseleave="isHovered = false"
|
||||
>
|
||||
<div v-if="isClicked" class="component-header" :style="headerStyle">
|
||||
<div v-if="componentSelected" class="component-header" :style="headerStyle">
|
||||
<span>{{ componentName }}</span>
|
||||
<button style="color: #1057CC" @click="handleFunction('edit')">编辑</button>
|
||||
<button style="color: #1057CC" @click="handleFunction('delete')">删除</button>
|
||||
<button style="color: #1057CC" @click="handleEditFunc">编辑</button>
|
||||
<button style="color: #1057CC" @click="handleDeleteFunc">删除</button>
|
||||
</div>
|
||||
<div class="component-content">
|
||||
<component
|
||||
@ -57,6 +57,7 @@ const componentText = computed(() => props.componentData?.text || '');
|
||||
const componentClass = computed(() => props.componentData?.class || []);
|
||||
const componentStyle = computed(() => props.componentData?.style || []);
|
||||
const componentSlots = computed(() => props.componentData?.slots || {});
|
||||
const componentSelected = computed(() => store.nowComponentsData?.id && props.componentData?.id === store.nowComponentsData?.id);
|
||||
|
||||
// 确保 componentProps 包含 disabled 属性
|
||||
const componentPropsWithDisabled = computed(() => ({
|
||||
@ -71,24 +72,24 @@ const getCurrentSchemeObj = () => {
|
||||
|
||||
// 控制悬停和点击状态
|
||||
const isHovered = ref(false);
|
||||
const isClicked = ref(false);
|
||||
|
||||
const handleClick = () => {
|
||||
isClicked.value = !isClicked.value;
|
||||
const currentComponent = getCurrentSchemeObj();
|
||||
console.log(`Component with id ${currentComponent.id} was clicked.`);
|
||||
if (currentComponent) {
|
||||
store.nowComponentsData = currentComponent
|
||||
console.log(`Component with id ${currentComponent?.id} was clicked.`);
|
||||
// 你可以在这里执行更多的逻辑,例如发出一个事件或调用一个方法
|
||||
};
|
||||
}
|
||||
|
||||
const handleFunction = (action: string) => {
|
||||
console.log(`Action: ${action}`);
|
||||
// 处理编辑或删除操作
|
||||
};
|
||||
const handleEditFunc = () => {
|
||||
|
||||
};
|
||||
const handleDeleteFunc = () => {
|
||||
store.deleteScheme(componentId.value);
|
||||
};
|
||||
|
||||
const headerStyle = ref({});
|
||||
|
||||
const targetContent = ref<HTMLElement | null>(null);
|
||||
|
||||
const adjustHeaderPosition = () => {
|
||||
const componentEl = document.getElementById(componentId.value);
|
||||
if (!componentEl) return;
|
||||
@ -137,11 +138,10 @@ const adjustHeaderPosition = () => {
|
||||
|
||||
onMounted(() => {
|
||||
console.log(props.componentData);
|
||||
adjustHeaderPosition();
|
||||
});
|
||||
|
||||
watch(() => isClicked.value, () => {
|
||||
if (isClicked.value) {
|
||||
watch(() => componentSelected.value, () => {
|
||||
if (componentSelected.value) {
|
||||
nextTick(() => {
|
||||
adjustHeaderPosition();
|
||||
});
|
||||
@ -153,7 +153,7 @@ watch(() => isClicked.value, () => {
|
||||
.dynamic-component {
|
||||
position: relative;
|
||||
border: 1px solid transparent; /* 默认透明边框 */
|
||||
transition: border 0.3s, box-shadow 0.3s;
|
||||
transition: box-shadow 0.1s;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
|
||||
@ -79,6 +79,7 @@ const scheme = computed<IPageComponent>(() => props.scheme || {} as IPageCompone
|
||||
// 使用 deep 选项来深度监听对象的变化
|
||||
watch(scheme, (value, oldValue) => {
|
||||
console.log("scheme Changed", value);
|
||||
if (value)
|
||||
store.updateScheme(value.id, value as IComponent);
|
||||
}, {deep: true});
|
||||
|
||||
|
||||
@ -5,19 +5,20 @@ import { sha256 } from 'js-sha256';
|
||||
// 缓存对象
|
||||
const idToObjectCache = new Map<string, IPageComponent>();
|
||||
|
||||
function findObjectById(obj, targetId) {
|
||||
function findObjectById(obj: any, targetId: string) {
|
||||
if (Array.isArray(obj)) {
|
||||
for (let item of obj) {
|
||||
let found = findObjectById(item, targetId);
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
const item = obj[i];
|
||||
if (item.id === targetId) {
|
||||
return { item, index: i, parent: obj };
|
||||
}
|
||||
const found = findObjectById(item, targetId);
|
||||
if (found) return found;
|
||||
}
|
||||
} else if (typeof obj === 'object' && obj !== null) {
|
||||
if (obj.id === targetId) {
|
||||
return obj;
|
||||
}
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
let found = findObjectById(obj[key], targetId);
|
||||
const found = findObjectById(obj[key], targetId);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
@ -30,9 +31,9 @@ const HISTORY_LENGTH = 20; // 默认队列长度
|
||||
export const useSchemeStore = defineStore('scheme', {
|
||||
state: () => ({
|
||||
designerMode: true,
|
||||
components: [],
|
||||
previewScheme: [],
|
||||
nowComponentsData: {},
|
||||
components: [] as IPageComponent[],
|
||||
previewScheme: [] as IPageComponent[],
|
||||
nowComponentsData: {} as IPageComponent,
|
||||
history: Array(HISTORY_LENGTH).fill(null), // 循环队列
|
||||
currentIndex: -1, // 当前索引
|
||||
currentLength: 0, // 当前队列中有效元素的数量
|
||||
@ -43,19 +44,19 @@ export const useSchemeStore = defineStore('scheme', {
|
||||
canRedo: (state) => state.currentIndex < state.currentLength - 1,
|
||||
},
|
||||
actions: {
|
||||
initPreviewScheme(value) {
|
||||
initPreviewScheme(value: IPageComponent[]) {
|
||||
this.previewScheme = value;
|
||||
this.nowComponentsData = value[0];
|
||||
this.nowComponentsData = value[0] || {} as IPageComponent;
|
||||
idToObjectCache.clear();
|
||||
this.history.fill(null); // 初始化队列
|
||||
this.currentIndex = -1;
|
||||
this.currentLength = 0;
|
||||
this.currentHash = ''; // 初始化当前哈希值
|
||||
},
|
||||
initComponents(value) {
|
||||
initComponents(value: IPageComponent[]) {
|
||||
this.components = value;
|
||||
},
|
||||
getSchemeObj(id) {
|
||||
getSchemeObj(id: string) {
|
||||
// 检查缓存
|
||||
if (idToObjectCache.has(id)) {
|
||||
return idToObjectCache.get(id);
|
||||
@ -63,19 +64,78 @@ export const useSchemeStore = defineStore('scheme', {
|
||||
// 查找并缓存
|
||||
const obj = findObjectById(this.previewScheme, id);
|
||||
if (obj) {
|
||||
idToObjectCache.set(id, obj);
|
||||
idToObjectCache.set(id, obj.item);
|
||||
}
|
||||
return obj;
|
||||
return obj ? obj.item : null;
|
||||
},
|
||||
updateScheme(id, updates) {
|
||||
updateScheme(id: string, updates: Partial<IPageComponent>) {
|
||||
const currentStateHash = this.currentHash;
|
||||
const newObj = this.getSchemeObj(id);
|
||||
if (newObj) {
|
||||
Object.assign(newObj, updates);
|
||||
}
|
||||
const newStateHash = sha256(JSON.stringify(this.previewScheme));
|
||||
this.saveNewState(currentStateHash);
|
||||
},
|
||||
deleteScheme(id: string) {
|
||||
const currentStateHash = this.currentHash;
|
||||
const objToDelete = findObjectById(this.previewScheme, id);
|
||||
if (objToDelete) {
|
||||
const { item, index, parent } = objToDelete;
|
||||
parent.splice(index, 1);
|
||||
idToObjectCache.delete(id); // 从缓存中删除
|
||||
|
||||
// 如果新状态与当前状态不同,才保存到历史记录中
|
||||
// 清理 nowComponentsData
|
||||
if (this.nowComponentsData.id === id) {
|
||||
this.nowComponentsData = {} as IPageComponent;
|
||||
}
|
||||
|
||||
// 清理 history 中的引用
|
||||
this.cleanupReferences(id);
|
||||
}
|
||||
this.saveNewState(currentStateHash);
|
||||
},
|
||||
cleanupReferences(id: string) {
|
||||
// 清理 nowComponentsData
|
||||
if (this.nowComponentsData.id === id) {
|
||||
this.nowComponentsData = {} as IPageComponent;
|
||||
}
|
||||
|
||||
// 清理 history 中的引用
|
||||
for (let i = 0; i < this.currentLength; i++) {
|
||||
const historyState = this.history[i % HISTORY_LENGTH];
|
||||
if (historyState) {
|
||||
const obj = findObjectById(historyState, id);
|
||||
if (obj) {
|
||||
const { parent, index } = obj;
|
||||
parent.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
undo() {
|
||||
if (this.canUndo) {
|
||||
this.currentIndex--;
|
||||
const prevState = this.history[this.currentIndex % HISTORY_LENGTH];
|
||||
if (prevState) {
|
||||
this.previewScheme = prevState;
|
||||
this.nowComponentsData = this.previewScheme[0] || {} as IPageComponent;
|
||||
this.currentHash = sha256(JSON.stringify(this.previewScheme));
|
||||
}
|
||||
}
|
||||
},
|
||||
redo() {
|
||||
if (this.canRedo) {
|
||||
this.currentIndex++;
|
||||
const nextState = this.history[this.currentIndex % HISTORY_LENGTH];
|
||||
if (nextState) {
|
||||
this.previewScheme = nextState;
|
||||
this.nowComponentsData = this.previewScheme[0] || {} as IPageComponent;
|
||||
this.currentHash = sha256(JSON.stringify(this.previewScheme));
|
||||
}
|
||||
}
|
||||
},
|
||||
saveNewState(currentStateHash: string) {
|
||||
const newStateHash = sha256(JSON.stringify(this.previewScheme));
|
||||
if (currentStateHash !== newStateHash) {
|
||||
this.currentHash = newStateHash;
|
||||
// 如果不是最新的状态,则清除之后的所有状态
|
||||
@ -87,28 +147,6 @@ export const useSchemeStore = defineStore('scheme', {
|
||||
this.currentLength = this.currentIndex + 1;
|
||||
this.history[this.currentIndex % HISTORY_LENGTH] = JSON.parse(JSON.stringify(this.previewScheme));
|
||||
}
|
||||
},
|
||||
undo() {
|
||||
if (this.canUndo) {
|
||||
this.currentIndex--;
|
||||
const prevState = this.history[this.currentIndex % HISTORY_LENGTH];
|
||||
if (prevState) {
|
||||
this.previewScheme = prevState;
|
||||
this.nowComponentsData = this.previewScheme[0];
|
||||
this.currentHash = sha256(JSON.stringify(this.previewScheme));
|
||||
}
|
||||
}
|
||||
},
|
||||
redo() {
|
||||
if (this.canRedo) {
|
||||
this.currentIndex++;
|
||||
const nextState = this.history[this.currentIndex % HISTORY_LENGTH];
|
||||
if (nextState) {
|
||||
this.previewScheme = nextState;
|
||||
this.nowComponentsData = this.previewScheme[0];
|
||||
this.currentHash = sha256(JSON.stringify(this.previewScheme));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user