import { defineStore } from "pinia"; import { AlignEnum } from "@/enum/alignEnum"; import { LayerEnum } from "@/enum/layerEnum"; import { useProjectStore } from "@/store/modules/project"; import { cloneDeep } from "lodash"; import { CustomElement } from "#/project"; import { uuid } from "@/utils"; // import { recoverRecord } from "@/utils/recover"; // type RecordItem = { // info: Record; // type: "add" | "update" | "delete" | "init"; // snapshot: ProjectInfo; // }; type ActionState = { // 操作记录--最大记录10条 records: string[]; // 当前操作索引 activeIndex: number; appKey: number; copyCache: any; }; export const useAcionStore = defineStore({ id: "action", state(): ActionState { return { records: [], activeIndex: -1, appKey: 0, copyCache: null, }; }, getters: { projectStore: () => useProjectStore(), undoDisabled: (state) => state.activeIndex <= 0, redoDisabled: (state) => state.activeIndex === state.records.length - 1, }, actions: { initRecord() { this.records = [JSON.stringify(this.projectStore.projectInfo)]; this.activeIndex = 0; }, // addRecord({type, info }: RecordItem & { snapshot?: ProjectInfo}) { addRecord() { // 新增如果当前索引不是最后一条, 覆盖后面的记录 if (this.activeIndex < this.records.length - 1) { this.records.splice(this.activeIndex + 1, this.records.length); } this.records.push(JSON.stringify(this.projectStore.projectInfo)); // 新增如果超过10条记录,删除最早的一条 if (this.records.length > 10) { this.records.shift(); this.activeIndex--; } this.activeIndex = this.records.length - 1; }, /* 撤销 */ actionUndo() { if (this.activeIndex <= 0) return; --this.activeIndex; const projectInfo = JSON.parse(this.records[this.activeIndex]); this.projectStore.updateProjectInfo(projectInfo); this.appKey++; }, /* 重做 */ actionRedo() { ++this.activeIndex; const projectInfo = JSON.parse(this.records[this.activeIndex]); this.projectStore.updateProjectInfo(projectInfo); this.appKey++; }, actionClear() {}, /* 对齐 */ actionAlign(type: AlignEnum) { const activeElements = this.projectStore.currentSelectedElements; switch (type) { case AlignEnum.Bottom: { const maxY = Math.max( ...activeElements.map( (item) => item.container.props.y + item.container.props.height ) ); activeElements.forEach((item) => { this.projectStore.updateElement( item.key, "container.props.y", maxY - item.container.props.height ); }); break; } case AlignEnum.HorizontalCenter: { const maxX = Math.max( ...activeElements.map( (item) => item.container.props.x + item.container.props.width ) ); const minX = Math.min( ...activeElements.map((item) => item.container.props.x) ); const centerX = minX + (maxX - minX) / 2; activeElements.forEach((item) => { this.projectStore.updateElement( item.key, "container.props.x", centerX - item.container.props.width / 2 ); }); break; } case AlignEnum.VerticalCenter: { const maxY = Math.max( ...activeElements.map( (item) => item.container.props.y + item.container.props.height ) ); const minY = Math.min( ...activeElements.map((item) => item.container.props.y) ); const centerY = minY + (maxY - minY) / 2; activeElements.forEach((item) => { this.projectStore.updateElement( item.key, "container.props.y", centerY - item.container.props.height / 2 ); }); break; } case AlignEnum.Left: { const minX = Math.min( ...activeElements.map((item) => item.container.props.x) ); activeElements.forEach((item) => { this.projectStore.updateElement( item.key, "container.props.x", minX ); }); break; } case AlignEnum.Right: { const maxX = Math.max( ...activeElements.map( (item) => item.container.props.x + item.container.props.width ) ); activeElements.forEach((item) => { this.projectStore.updateElement( item.key, "container.props.x", maxX - item.container.props.width ); }); break; } case AlignEnum.Top: { const minY = Math.min( ...activeElements.map((item) => item.container.props.y) ); activeElements.forEach((item) => { this.projectStore.updateElement( item.key, "container.props.y", minY ); }); break; } default: } this.addRecord(); }, /* 图层调整 */ actionLayer(type: LayerEnum) { const activeElements = this.projectStore.currentSelectedElements; const elements = cloneDeep( this.projectStore.elements.sort((a, b) => a.zIndex - b.zIndex) ) as CustomElement[]; switch (type) { case LayerEnum.UP: { activeElements.forEach((item) => { const index = elements.findIndex( (element) => element.key === item.key ); if (item.zIndex === elements.length) return; elements.splice(index, 1); elements.splice(index + 1, 0, { ...item }); }); elements.forEach((item, index) => { item.zIndex = index + 1; }); elements.forEach((item) => { this.projectStore.updateElement(item.key, "zIndex", item.zIndex); }); break; } case LayerEnum.DOWN: { activeElements.forEach((item) => { const index = elements.findIndex( (element) => element.key === item.key ); if (item.zIndex === 1) return; elements.splice(index, 1); elements.splice(index - 1, 0, { ...item }); }); elements.forEach((item, index) => { item.zIndex = index + 1; }); elements.forEach((item) => { this.projectStore.updateElement(item.key, "zIndex", item.zIndex); }); break; } case LayerEnum.TOP: { activeElements.forEach((item) => { const index = elements.findIndex( (element) => element.key === item.key ); if (item.zIndex === elements.length) return; elements.splice(index, 1); elements.push({ ...item }); }); elements.forEach((item, index) => { item.zIndex = index + 1; }); elements.forEach((item) => { this.projectStore.updateElement(item.key, "zIndex", item.zIndex); }); break; } case LayerEnum.BOTTOM: { activeElements.forEach((item) => { const index = elements.findIndex( (element) => element.key === item.key ); if (item.zIndex === 1) return; elements.splice(index, 1); elements.unshift({ ...item }); }); elements.forEach((item, index) => { item.zIndex = index + 1; }); elements.forEach((item) => { this.projectStore.updateElement(item.key, "zIndex", item.zIndex); }); break; } } this.addRecord(); }, /* 添加组合 */ actionGroup() { const elements = this.projectStore.currentSelectedElements; const key = uuid(); // 1、移除元素 elements.forEach((element) => { this.projectStore.removeElement(element.key); }); const minX = Math.min(...elements.map((item) => item.container.props.x)); const minY = Math.min(...elements.map((item) => item.container.props.y)); const maxX = Math.max(...elements.map((item) => item.container.props.x + item.container.props.width)); const maxY = Math.max(...elements.map((item) => item.container.props.y + item.container.props.height)); const maxZIndex = Math.max(...elements.map((item) => item.zIndex)); const groupIndex = this.projectStore.elements.filter((item) => item.componentType === "group").length + 1; // 重新计算子元素位置 elements.forEach((item) => { item.container.props.x -= minX; item.container.props.y -= minY; item.parentKey = key; }); const group: CustomElement = { key, name: "组合" + groupIndex, componentType: "group", visible: true, locked: false, zIndex: maxZIndex, container: { style: {}, props: { width: maxX - minX, height: maxY - minY, x: minX, y: minY, }, }, children: elements, collapsed: false, events: [], animations: [], props: {} } // 2、添加组合元素 this.projectStore.addElement(group); }, /* 拆分组合元素 */ actionUngroup() { const group = this.projectStore.currentSelectedElements[0]; // 1、取出子元素 const elements = group.children?.map((item) => { // 2、计算子元素位置 item.container.props.x += group.container.props.x; item.container.props.y += group.container.props.y; delete item.parentKey; return item; }); // 3、移除组 this.projectStore.removeElement(group.key); // 4、添加子元素 elements?.forEach((item) => { this.projectStore.addElement(item, undefined, true); }); }, /* 复制 */ actionCopy() { const elements = this.projectStore.currentSelectedElements; this.copyCache = JSON.stringify(elements); }, /* 粘贴 */ actionPaste() { try { const elements = JSON.parse(this.copyCache); const offsetX = 10; const offsetY = 10; elements.forEach((element: CustomElement) => { element.key = uuid(); element.container.props.x += offsetX; element.container.props.y += offsetY; this.projectStore.addElement(element); }); } catch (error) { console.log(error); } } }, });