import { cloneDeep, pick } from "lodash"; import { nanoid } from "nanoid"; import { Exception, queenApi } from "queenjs"; import { EditorModule } from ".."; import { ScreenshotCtrl } from "../../controllers/ScreenshotCtrl"; import { ObjsContainer } from "../../controllers/SelectCtrl/ObjsContainer"; import { CompObject } from "../../controllers/SelectCtrl/compObj"; import { Matrix } from "../../controllers/SelectCtrl/matrix"; import { DesignComp } from "../../objects/DesignTemp/DesignComp"; import { ICompKeys, Layout } from "../../typings"; import CompSave from "../../components/CompSave"; import { getKeyThenIncreaseKey } from "ant-design-vue/lib/message"; import { cloneObj, createObj, history } from "../../objects/DesignTemp/factory"; const ctrlState = { selected: [] as string[], type: 0, // 1 ctrlc 2 ctrlx 3 ctrlq cardId: "", //当前的卡片Id screenId: "", //屏幕Id selWidth: 0, selX: 0, selY: 0, }; export const editActions = EditorModule.action({ async addImageToDesign(url) { queenApi.showLoading("图片加载中"); const maxW = this.controls.screenCtrl.getCurrScreenWidth(); try { const temImg: any = await this.helper.loadImage(url); const ratio = temImg.width / temImg.height; const W = temImg.width > maxW ? maxW : temImg.width; const H = W / ratio; await this.actions.clickCompToDesign("Image", (comp) => { comp.setSize(W, H); comp.value.url = url; }); } catch (e) { queenApi.hideLoading(); queenApi.messageError("图片加载失败"); return; } queenApi.hideLoading(); }, async dragAddImageToDesign(e: MouseEvent, url) { const page = this.controls.pageCtrl; if (!page.currStreamCardId) { queenApi.messageError("请先选中一个卡片"); return; } queenApi.showLoading("图片加载中"); const maxW = this.controls.screenCtrl.getCurrScreenWidth(); try { const temImg: any = await this.helper.loadImage(url); const ratio = temImg.width / temImg.height; const W = temImg.width > maxW ? maxW : temImg.width; const H = W / ratio; const currCard = page.currStreamCard; const currComp = createObj({ compKey: "Image" }, false); currComp.setSize(W, H); currComp.value.url = url; page.designData.compMap[currComp.id] = currComp; // page.setCompPid(currComp.id, page.currStreamCardId); const childIds = [...page.currStreamCard.children.default]; childIds.push(currComp.id); currCard.children.setDefault(childIds); this.controls.editorCtrl.clickPickComp(currComp.id); this.actions.centerLastComp(e); } catch (e) { queenApi.hideLoading(); queenApi.messageError("图片加载失败"); return; } queenApi.hideLoading(); history.submit(); }, async dragAddVideoToDesign(e: MouseEvent, url) { const page = this.controls.pageCtrl; if (!page.currStreamCardId) { queenApi.messageError("请先选中一个卡片"); return; } queenApi.showLoading("视频加载中"); // const maxW = this.controls.screenCtrl.getCurrScreenWidth(); try { // const temImg :any = await this.helper.loadImage(url); // const ratio = temImg.width / temImg.height; // const W = temImg.width > maxW ? maxW : temImg.width; // const H = W / ratio; const currCard = page.currStreamCard; const currComp = createObj({ compKey: "Video" }, false); // currComp.setSize(W, H ); currComp.value.url = url; page.designData.compMap[currComp.id] = currComp; // page.setCompPid(currComp.id, page.currStreamCardId); const childIds = [...page.currStreamCard.children.default]; childIds.push(currComp.id); currCard.children.setDefault(childIds); this.controls.editorCtrl.clickPickComp(currComp.id); this.actions.centerLastComp(e); } catch (e) { queenApi.hideLoading(); queenApi.messageError("图片加载失败"); return; } queenApi.hideLoading(); history.submit(); }, // 通过点击添加组件到画布 async clickCompToDesign( compKey: ICompKeys, cb?: (comp: DesignComp) => void, history = true ) { const page = this.controls.pageCtrl; if (!page.currStreamCardId) { queenApi.messageError("请先选中一个卡片"); return; } let yOffset = 0; if ( page.state.currCompId != page.state.currStreamCardId && page.state.currCompId != "root" ) { const bound = this.helper.getCardCompBound(page.state.currCompId); yOffset = bound.y + bound.h; } let currCard = page.currStreamCard; const currComp = createObj({ compKey }, false); // debugger //@ts-ignore const objs: any[] = currComp.children.objs || []; if (objs.length > 0) { objs.forEach((o) => { page.designData.compMap[o.id] = o; page.setCompPid(o.id, currComp.id); }); } page.designData.compMap[currComp.id] = currComp; page.setCompPid(currComp.id, currCard.id); const childIds = [...currCard.children.default]; childIds.push(currComp.id); currCard.children.setDefault(childIds); const compId = currComp.id; cb?.(currComp); const w = this.controls.screenCtrl.getCurrScreenWidth(); //添加组件到当前选中的组件下面 let xOffset = this.helper.designSizeToPx( w / 2.0 - (currComp.layout.size?.[0] || w) / 2 ); const obj = new CompObject(currComp); //没有选中组件添加到当前卡片最后 const children = currCard.children.default || []; if (yOffset == 0 && children.length >= 2) { const prevCompIndex = children.indexOf(compId) - 1; const bound = this.helper.getCardCompBound(children[prevCompIndex]); yOffset = bound.y + bound.h; } obj.worldTransform.translate(xOffset, yOffset); currComp.layout.transformMatrix = obj.worldTransform.getMatrixStr(); this.controls.editorCtrl.clickPickComp(compId); this.helper.extendStreamCard(currCard.id); if (compKey == "Text") { this.actions.textFocus(compId, true); } this.controls.cropCtrl.close(); if (history) this.history.submit(); }, // 通过点击添加组件到画布 async clickCompUserToDesign(id: string, isSys) { const page = this.controls.pageCtrl; if (!page.currStreamCardId) { queenApi.messageError("请先选中一个卡片"); return; } const { result } = await this.https.getCompDetail(id, isSys); const currCard = page.currStreamCard; const comp = page.addUserCard(result); const compId = comp.id; const childIds = [...(currCard.children.default || [])]; childIds.push(compId); currCard.children.setDefault(childIds); page.setCompPid(compId, currCard.id); this.actions.initAddedCompPos(this.store.currCompId, compId, currCard.id); this.controls.editorCtrl.clickPickComp(compId); history.submit(); }, initAddedCompPos(currId: string, addedId: string, cardId: string) { let yOffset = 0; if (currId != this.controls.pageCtrl.currStreamCardId && currId != "root") { const paths = this.helper.getCompTrees(currId); const bound = this.helper.getCardCompBound(paths[2].id); yOffset = bound.y + bound.h; } const currComp = this.helper.findComp(addedId) as DesignComp; const w = this.controls.screenCtrl.getCurrScreenWidth(); //添加组件到当前选中的组件下面 let xOffset = this.helper.designSizeToPx( w / 2.0 - (currComp.layout.size?.[0] || w) / 2 ); const obj = new CompObject(currComp); const currCard = this.helper.findComp(cardId) as DesignComp; //没有选中组件添加到当前卡片最后 const children = currCard.children.default || []; if (yOffset == 0 && children.length >= 2) { const prevCompIndex = children.indexOf(addedId) - 1; const bound = this.helper.getCardCompBound(children[prevCompIndex]); yOffset = bound.y + bound.h; } obj.worldTransform.translate(xOffset, yOffset); currComp.layout.transformMatrix = obj.worldTransform.getMatrixStr(); this.helper.extendStreamCard(currCard.id); this.controls.cropCtrl.close(); }, // 通过拖拽添加组件到画布 async dragCompToDesign(event: MouseEvent, compKey: string, data: any) { const page = this.controls.pageCtrl; if (compKey == "CompCard") { const { result } = await this.https.getCompDetail(data.id, data.isSys); const comp = page.addUserCard(result); const currCard = page.currStreamCard; const compId = comp.id; const childIds = [...(currCard.children.default || [])]; childIds.push(compId); currCard.children.setDefault(childIds); page.setCompPid(compId, currCard.id); this.controls.editorCtrl.clickPickComp(compId); } else { await this.actions.addCompToDesign(compKey as any); } setTimeout(() => { this.actions.centerLastComp(event); const currComp = this.controls.pageCtrl.currComp; if (compKey == "Text") { this.actions.textFocus(currComp.id, true); } history.submit(); }, 100); }, centerLastComp(event: MouseEvent) { const currCardDom = this.controls.pageCtrl.currStreamCard.$el; const cardPoints = this.helper.getPointOffsetWith(event, currCardDom); const page = this.controls.pageCtrl; let selCtrl = this.controls.selectCtrl; const w = this.controls.screenCtrl.getCurrScreenWidth(); selCtrl.translate( this.helper.designSizeToPx( w / 2.0 - (page.currComp.layout.size?.[0] || w) / 2 ), cardPoints.y ); this.helper.extendStreamCard(page.state.currStreamCardId); this.controls.cropCtrl.close(); }, // 添加组件到画布 async addCompToDesign(compKey: ICompKeys, index?: number) { const page = this.controls.pageCtrl; if (!page.state.currStreamCardId) { //必须选中一个streamCard return; } if (compKey == "Container") { const compId = page.insertDesignCard(index); this.controls.editorCtrl.clickPickComp(compId); return; } const compId = page.insertCompContainer( compKey, this.controls.pageCtrl.currStreamCard ); this.controls.editorCtrl.clickPickComp(compId); }, pickParentComp(compId: string) { const page = this.controls.pageCtrl; const parentComp = this.helper.findParentComp(compId); parentComp && page.setCurrComp(parentComp.id); }, ctrlc() { const page = this.controls.pageCtrl; ctrlState.selected = []; const children = page.currStreamCard.children.default || []; const gizmo = this.controls.selectCtrl.gizmo; const selected = gizmo.selected.map((item) => item.comp.id); children.forEach((c) => { if (selected.indexOf(c) > -1) { ctrlState.selected.push(c); } }); ctrlState.screenId = this.controls.screenCtrl.currScreenId; ctrlState.cardId = page.currStreamCardId; ctrlState.type = 1; const objc = this.controls.selectCtrl.objContainer; ctrlState.selWidth = this.helper.pxToDesignSize(objc.width); objc.setPivot(0); const currX = objc.parent.x, currY = objc.parent.y; ctrlState.selX = currX; ctrlState.selY = currY; objc.setPivot(4); }, copyLastSelected() { if (this.store.currCompId && this.store.currCompId != "root") { ctrlState.selected = [this.store.currCompId]; ctrlState.cardId = this.controls.pageCtrl.currStreamCardId; ctrlState.type = 1; } }, setSameSize(isWidth: boolean) { const selectCtrl = this.controls.selectCtrl; const gizmo = selectCtrl.objContainer; const layout = this.controls.pageCtrl.currComp.layout; const w = this.controls.screenCtrl.getCurrScreenWidth(); if (this.selected.length == 1) { const size: any = layout.size.slice(0); let isSame = false; if (isWidth) { isSame = w == size[0]; size[0] = w; } else { isSame = size[1] == this.controls.pageCtrl.currStreamCard.layout.size[1]; size[1] = this.controls.pageCtrl.currStreamCard.layout.size[1]; } if (!isSame) { layout.setSize(size); this.history.submit(); } return; } const anchorBox = this.helper.findComp(gizmo.state.lastId); if (!anchorBox) return; gizmo.parent.children.forEach((c) => { const child = c as CompObject; const r = child.getBox(); if (isWidth) child.comp.layout.size[0] = anchorBox.layout.size[0]; else child.comp.layout.size[1] = anchorBox.layout.size[1]; }); gizmo.updateSize(); selectCtrl.upgateGizmoStyle(); history.submit(); }, toogleGroup() { const gizmo = this.controls.selectCtrl.gizmo; if (gizmo.selected.length > 1) { this.actions.createGroupComps(); return; } if (gizmo.selected.length == 1) { const c = gizmo.selected[0].comp; if (c.compKey == "Group") { this.actions.cancelGroupComps(c); } } }, ctrlq() { const page = this.controls.pageCtrl; if (!page.currCompId) return; ctrlState.selected = [page.currCompId]; ctrlState.screenId = this.controls.screenCtrl.currScreenId; ctrlState.cardId = page.currStreamCardId; ctrlState.type = 3; }, ctrlx() { //console.log("ctrlv ", this.store.selected); //console.log("ctrlv ", this.store.selected); const page = this.controls.pageCtrl; const gizmo = this.controls.selectCtrl.gizmo; const selected = gizmo.selected.map((item) => item.comp.id); //保持图层顺序 ctrlState.selected = []; const children = page.currStreamCard.children.default || []; children.forEach((c) => { if (selected.indexOf(c) > -1) { ctrlState.selected.push(c); } }); ctrlState.cardId = page.state.currStreamCardId; ctrlState.type = 2; ctrlState.screenId = this.controls.screenCtrl.currScreenId; const objc = this.controls.selectCtrl.objContainer; ctrlState.selWidth = this.helper.pxToDesignSize(objc.width); objc.setPivot(0); const currX = objc.parent.x, currY = objc.parent.y; ctrlState.selX = currX; ctrlState.selY = currY; objc.setPivot(4); }, ctrlv() { if (ctrlState.selected.length < 1) return; const ctrl = this.controls.pageCtrl; const news: string[] = []; const deepCopy = (c: DesignComp) => { const childs = c.children.default || []; if (childs.length > 0) { childs.forEach((id, index) => { const cp = this.helper.findComp(id) as DesignComp; const cp1 = cloneObj(cp); ctrl.compMap[cp1.id] = cp1; ctrl.setCompPid(cp1.id, c.id); childs[index] = cp1.id; deepCopy(cp1); }); } }; ctrlState.selected.forEach((c) => { const cp = this.helper.findComp(c) as DesignComp; const cp1 = cloneObj(cp); news.push(cp1.id); ctrl.compMap[cp1.id] = cp1; ctrl.setCompPid(cp1.id, ctrl.currStreamCardId); deepCopy(cp1); }); this.actions.addComps(news); this.controls.selectCtrl.gizmo.selectObjs(news); //剪辑 if (ctrlState.type == 2) { //剪辑删除原来的组件 const card = this.helper.findComp(ctrlState.cardId) as DesignComp; const childs = card.children.default?.slice(0) || []; ctrlState.selected.forEach((s) => { let i = childs.indexOf(s); if (i != -1) { childs.splice(i, 1); } }); card.children.default = childs; this.helper.extendStreamCard(ctrlState.cardId); ctrlState.selected = []; } //获取当前选中的内容 if (ctrlState.cardId != ctrl.currStreamCardId) { //跨卡片拷贝 let pox = this.helper.getCardNextPosY( ctrl.currStreamCardId, ctrlState.selWidth ); this.controls.selectCtrl.translate(0, pox.y - ctrlState.selY); return; } if (ctrlState.screenId == this.controls.screenCtrl.currScreenId) { this.controls.selectCtrl.translate(20, 20); } history.submit(); }, addComps(ids: string[]) { const childs = this.controls.pageCtrl.currStreamCard.children.default.slice(0); childs.push(...ids); this.controls.pageCtrl.currStreamCard.children.setDefault(childs); }, ctrlAndA() { const childrens = ( this.controls.pageCtrl.currStreamCard.children.default || [] ).slice(0); this.controls.selectCtrl.gizmo.selectObjs(childrens); }, // 删除组件 removeSelectComps() { const selected = this.controls.selectCtrl.gizmo.selected.slice(0); this.controls.editorCtrl.clickPickComp(""); let n = selected.length; while (n--) { this.actions.removeComp(selected[n].comp.id); } history.submit(); }, // 删除组件 removeComp(compId: string, submitHistory = false) { const ctrl = this.controls.pageCtrl; const paths = this.helper.getCompTrees(compId); if (!paths[2]) { if (this.helper.isStreamCard(compId)) { this.actions.removeStreamCard(compId); return; } return; } compId = paths[2].id; if (this.helper.isCompCanDelete(compId)) { if (this.helper.isStreamCard(compId)) { this.actions.removeStreamCard(compId); return; } const cardid = ctrl.currStreamCardId; if (compId === ctrl.currCompId) { ctrl.setCurrComp(ctrl.currStreamCardId); } ctrl.deleteComp(compId); this.helper.extendStreamCard(cardid); this.controls.editorCtrl.clickPickComp(""); } if (submitHistory) { history.submit(); } }, async removeStreamCard(compId: string) { const ctrl = this.controls.pageCtrl; await queenApi.showConfirm({ title: "删除", content: "确认删除当前页面?" }); let nextCard = ctrl.currStreamCardId; if (compId == ctrl.currStreamCardId) { const i = ctrl.streamCardIds.indexOf(compId); nextCard = ctrl.streamCardIds[i + 1]; if (!nextCard) { nextCard = ctrl.streamCardIds[i - 1]; } } this.controls.selectCtrl.gizmo.selectObjs([]); this.controls.propsCtrl.showProp("root"); ctrl.setCurrComp(nextCard); ctrl.deleteComp(compId); }, // 移动组件顺序 moveComp(selIndex: number, targetIndex: number) { this.controls.editorCtrl.clickPickComp("root"); if (selIndex === targetIndex) return; this.controls.pageCtrl.moveComp(selIndex, targetIndex); }, // 保存容器为组件 async saveAsComp(comp: DesignComp) { const ctrl = this.controls.pageCtrl; try { const CompSave = this.components.CompSave as any; let title = ""; let type = "comp"; try { const ret: any = await queenApi.dialog(, { width: "300px", title: "保存到我的", }); if (!ret) { return; } title = ret.title; type = ret.type; } catch (error) { return; } console.log(title, type); // 组件封面 const blob = await new ScreenshotCtrl().snap({ element: comp.$el, }); const thumbnail = URL.createObjectURL(blob); // const title = await queenApi.showInput({ // title: "保存到我的", // defaultValue: this.controls.compUICtrl.state.components.get( // comp.compKey // )?.name, // }); const ddata = ctrl.toJson(); const data = { title, type, thumbnail, compMap: ddata.compMap, }; this.helper.clearUnusedComps(data.compMap, comp.id); data.compMap.root = data.compMap[comp.id]; data.compMap.root.id = "root"; //清除平移距离 const mtx = Matrix.createFromMatrixStr( data.compMap.root.layout.transformMatrix as string ); mtx.tx = 0; mtx.ty = 0; data.compMap.root.layout.transformMatrix = mtx.getMatrixStr(); delete data.compMap[comp.id]; queenApi.showLoading("保存中"); this.controls.uploader.ignoreDashField = true; await this.controls.uploader.uploadBlobs(data); await this.https.createComp(data); queenApi.messageSuccess("保存成功"); } catch (error: any) { throw Exception.error(error.toString()); } finally { queenApi.hideLoading(); } }, // 保存项目 async saveDesign() { const ctrl = this.controls.pageCtrl; try { // 清除无用组件 this.helper.clearProjectUnusedComps(ctrl.designData.compMap); const c = this.controls.screenCtrl; c.saveScreenPage(); const root = this.helper.findRootComp() as DesignComp; root.value.useFor = c.state.screen.useFor; root.value.pageMode = c.state.screen.pageMode; root.value.pageSizeType = c.state.screen.pageSizeType; // 封面截屏 if (!ctrl.designData.thumbnail) { await this.actions.updateThumbnailByScreenshot(); } queenApi.showLoading("保存中"); await this.controls.uploader.uploadBlobs(ctrl.designData); if (this.store.isWk) { await this.https[this.store.isEditPage ? "saveWkDesign" : "saveComp"]( ctrl.toJson() ); } else { await this.https[this.store.isEditPage ? "saveDesign" : "saveComp"]( ctrl.toJson() ); } queenApi.messageSuccess("保存成功"); } catch (error: any) { throw Exception.error(error.toString()); } finally { queenApi.hideLoading(); } }, // 截屏保存封面 async updateThumbnailByScreenshot(autoSave?: boolean) { const ctrl = this.controls.pageCtrl; try { const rootComp = ctrl.rootPage; if (!rootComp) return; queenApi.showLoading("截屏中"); const blob = await new ScreenshotCtrl().snap({ element: rootComp.$el, ratio: this.store.isEditComp ? 0 : 1, }); const thumbnail = URL.createObjectURL(blob); ctrl.setDesignThumbnail(thumbnail); if (autoSave) { await this.controls.uploader.uploadBlobs(ctrl.designData); await this.https[this.store.isEditPage ? "saveDesign" : "saveComp"]( pick(ctrl.designData, ["_id", "thumbnail"]) ); queenApi.messageSuccess("保存成功"); } } catch (error: any) { throw Exception.error(error.toString()); } finally { queenApi.hideLoading(); } }, // 设置组件变换 setCompTransformMatrix(comp: DesignComp, transformMatrix: string) { if (!comp) return; comp.layout.transformMatrix = transformMatrix; }, // 设置组件显示隐藏 setCompVisible(comp: DesignComp) { comp.layout.visible = comp.layout.visible === false ? true : false; }, // 组件重命名 async resetCompName(comp: DesignComp) { const res = await queenApi.showInput({ title: "重命名", defaultValue: comp.layout.cusName, }); if (!res) return; comp.layout.cusName = res; }, // 清除组件变换 // clearCompTransform(comp: DesignComp) { // comp.layout.margin = ""; // comp.layout.transform = undefined; // }, // 设置组件锁定状态 setCompLock(comp: DesignComp) { comp.layout.setLocked(!comp.layout.locked); }, // 设置组件层级 setCompLayer(comp: DesignComp, offset: number) { const currCard = this.controls.pageCtrl.currStreamCard; const cards = currCard.children.default.slice(0); const i = cards.indexOf(comp.id); if (i == -1) return; if (offset < 0) { //向下移动 if (i == 0) return; const temp = cards[i - 1]; cards[i - 1] = comp.id; cards[i] = temp; currCard.children.setDefault(cards); history.submit(); return; } if (i == cards.length - 1) return; const temp = cards[i + 1]; cards[i + 1] = comp.id; cards[i] = temp; currCard.children.setDefault(cards); history.submit(); }, //横向对齐 setAlignX(flag: 0 | 1 | 2 | 3, isGroup = false) { console.log("alignX"); const selectCtrl = this.controls.selectCtrl; const w = this.helper.designSizeToPx( this.controls.screenCtrl.getCurrScreenWidth() ); const gizmo = selectCtrl.gizmo; if (gizmo.selected.length == 1 || isGroup) { const box = gizmo.getBound(); switch (flag) { case 0: selectCtrl.translate(-box.left, 0); break; case 1: selectCtrl.translate(-(box.center.x - w / 2.0), 0); break; case 2: selectCtrl.translate(w - box.right, 0); break; } history.submit(); return; } //多选元素对齐模式 const anchorBox = this.helper.findComp(gizmo.state.lastId); if (!anchorBox) return; const anchor = new CompObject(anchorBox); const anchorRect = anchor.getBox(); let min = 10000, max = -10000; let step = 0; if (flag == 3) { //Y轴均匀排布 gizmo.parent.children.forEach((c) => { const child = c as CompObject; const r = child.getBox(); const x = r.x + r.w / 2.0; if (x < min) min = x; if (x > max) max = x; }); const stepCount = gizmo.parent.children.length; step = (max - min) / (stepCount - 1); const stepIndexMap: any = {}; gizmo.parent.children.forEach((c) => { const child = c as CompObject; const r = child.getBox(); const x = r.x + r.w / 2.0; let minIndex = -1; let minV = 10000; for (let i = 0; i < stepCount; i++) { const ty = i * step + min; if (Math.abs(x - ty) < minV && !stepIndexMap[i]) { minV = Math.abs(x - ty); minIndex = i; } } stepIndexMap[minIndex] = true; child.translate(minIndex * step + min - x, 0); }); gizmo.parent.updateTransform(); history.submit(); return; } gizmo.parent.children.forEach((c) => { const child = c as CompObject; if (child.comp.id == gizmo.state.lastId) return; const r = child.getBox(); switch (flag) { case 0: child.translate(anchorRect.x - r.x, 0); break; case 1: child.translate( anchorRect.x + anchorRect.w / 2.0 - (r.x + r.w / 2.0), 0 ); break; case 2: child.translate(anchorRect.x + anchorRect.w - (r.x + r.w), 0); break; } }); gizmo.parent.updateTransform(); history.submit(); }, setAlignY(flag: 0 | 1 | 2 | 3, isGroup = false) { const selectCtrl = this.controls.selectCtrl; const gizmo = selectCtrl.gizmo; if (gizmo.selected.length == 1 || isGroup) { const objc = selectCtrl.objContainer; const box = objc.getBound(); const card = new CompObject(this.controls.pageCtrl.currStreamCard); const cardBox = card.getBox(); switch (flag) { case 0: selectCtrl.translate(0, -box.top); break; case 1: selectCtrl.translate(0, -(box.center.y - cardBox.h / 2.0)); break; case 2: selectCtrl.translate(0, cardBox.h - box.bottom); break; } history.submit(); return; } const anchorBox = this.helper.findComp(gizmo.state.lastId); if (!anchorBox) return; const anchor = new CompObject(anchorBox); const anchorRect = anchor.getBox(); const objc = selectCtrl.objContainer; let min = 10000; let max = -10000; let step = 0; if (flag == 3) { //Y轴均匀排布 objc.parent.children.forEach((c) => { const child = c as CompObject; const r = child.getBox(); const y = r.y + r.h / 2.0; if (y < min) min = y; if (y > max) max = y; }); const stepCount = objc.parent.children.length; step = (max - min) / (stepCount - 1); const stepIndexMap: any = {}; objc.parent.children.forEach((c) => { const child = c as CompObject; const r = child.getBox(); const y = r.y + r.h / 2.0; let minIndex = -1; let minV = 10000; for (let i = 0; i < stepCount; i++) { const ty = i * step + min; if (Math.abs(y - ty) < minV && !stepIndexMap[i]) { minV = Math.abs(y - ty); minIndex = i; } } stepIndexMap[minIndex] = true; child.translate(0, minIndex * step + min - y); }); gizmo.parent.updateTransform(); history.submit(); return; } objc.parent.children.forEach((c) => { const child = c as CompObject; if (child.comp.id == gizmo.state.lastId) return; const r = child.getBox(); switch (flag) { case 0: child.translate(0, anchorRect.y - r.y); break; case 1: child.translate( 0, anchorRect.y + anchorRect.h / 2.0 - (r.y + r.h / 2.0) ); break; case 2: child.translate(0, anchorRect.y + anchorRect.h - (r.y + r.h)); break; } }); history.submit(); }, // 宽度铺满 fullCompWidth(comp: DesignComp) { comp.layout.size[0] = this.controls.screenCtrl.getCurrScreenWidth(); }, // 取消打组 cancelGroupComps(groupComp: DesignComp) { const childs = groupComp.children.default; const gizmo = this.controls.selectCtrl.gizmo; const parentMtrx = gizmo.parent.worldTransform.clone(); gizmo.selectObjs([]); //取消选择 childs.forEach((o) => { const obj = this.helper.findComp(o) as DesignComp; const mxt = Matrix.createFromMatrixStr( obj.layout.transformMatrix as string ); mxt.prepend(parentMtrx); obj.layout.setTransformMatrix(mxt.getMatrixStr()); }); const paths = this.helper.getCompTrees(groupComp.id); const card = paths[1]; const parentChilds = (card.children.default || []).filter( (item) => item != groupComp.id ); parentChilds.push(...childs); const page = this.controls.pageCtrl; childs.forEach((item) => { page.setCompPid(item, card.id); }); card.children.setDefault(parentChilds); this.controls.editorCtrl.clickPickComp(childs[0]); history.submit(); }, createGroupComps() { const gizmo = this.controls.selectCtrl.gizmo; const page = this.controls.pageCtrl; const sels = gizmo.selected.map((item) => item.comp.id); const id = this.controls.compUICtrl.createCompId("Group"); page.setCompPid(id, page.currStreamCardId); const comp = this.helper.findComp(id) as DesignComp; const chils = this.controls.pageCtrl.currStreamCard.children.default || []; const newChilds: any = []; const groupChilds: string[] = []; chils.forEach((c) => { if (sels.indexOf(c) == -1) newChilds.push(c); else { groupChilds.push(c); } }); newChilds.push(id); //更新节点的新位置 const newMatrixMap: any = {}; gizmo.parent.children.forEach((obj) => { const cobj = obj as CompObject; const comp = cobj.comp; newMatrixMap[comp.id] = cobj.localTransform.getMatrixStr(); }); page.currStreamCard.children.setDefault(newChilds); //再添加新的节点 comp.layout.setSize([ this.helper.pxToDesignSize(gizmo.width), this.helper.pxToDesignSize(gizmo.height), ]); comp.layout.setTransformMatrix(gizmo.parent.worldTransform.getMatrixStr()); this.controls.selectCtrl.gizmo.selectObjs([]); groupChilds.forEach((c) => { const comp = this.helper.findComp(c) as DesignComp; comp.layout.setTransformMatrix(newMatrixMap[c]); page.setCompPid(c, id); }); comp.children.setDefault(groupChilds); this.controls.propsCtrl.showProp(comp.id); this.controls.selectCtrl.gizmo.selectObjs([comp.id]); history.submit(); }, handleSelectMoving(key: string) { if (this.controls.selectCtrl.gizmo.selected.length < 1) return; let x = 0, y = 0; switch (key) { case "left": x = -1; break; case "right": x = 1; break; case "up": y = -1; break; case "down": y = 1; break; } this.controls.selectCtrl.translate(x * 0.5, y * 0.5); this.controls.selectCtrl.assistCtrl?.flashDrawCardDists(); history.submit(); }, // 点击模板 async clickTplToDesign(record) { const ctrl = this.controls.pageCtrl; const res = await queenApi.showConfirm({ title: "", content: "要替换正在编辑的内容?", }); if (!res) return; const frameData = await this.https.getDesignDetail(record._id, { isSys: true, }); const { compMap, content, desc, thumbnail, title, _id } = frameData.result; const designData = { _id: ctrl.designData._id, version: ctrl.designData.version, compMap, content, desc, thumbnail, title, }; this.controls.editorCtrl.clickPickComp("root"); ctrl.setDesignData(designData); ctrl.state.setDesignId(_id as string); }, });