import { isPc } from "@queenjs/utils"; import { nanoid } from "nanoid"; import { EditorModule } from ".."; import { CompObject } from "../../controllers/SelectCtrl/compObj"; import { Matrix } from "../../controllers/SelectCtrl/matrix"; import { Design_Page_Size, Design_Pixel_Ratio } from "../../dicts/CompOptions"; import { DesignComp } from "../../objects/DesignTemp/DesignComp"; import { createCompStyle, createViewStyles, } from "../../objects/DesignTemp/creates/createCompStyle"; import { Layout } from "../../typings"; import { designSizeToPx, pxToDesignSize } from "../utils"; export const helpers = EditorModule.helper({ pxToDesignSize(value: number) { return pxToDesignSize(value); }, designSizeToPx(value: number) { return designSizeToPx(value); }, designToNaturalSize( value: number, options?: { adaptiveH?: boolean } ): string { if (options?.adaptiveH && !isPc()) { value = value * ((window.innerHeight * Design_Pixel_Ratio) / Design_Page_Size[1]); } return designSizeToPx(value) + "px"; }, findComp(compId: string) { const compMap = this.controls.pageCtrl.compMap; if (!compMap) return; const comp = compMap[compId]; if (comp) return comp; }, isStreamCard(compId: string) { return this.controls.pageCtrl.streamCardIds.indexOf(compId) > -1; }, isGroupCompChild(compId: string) { const comps = this.helper.getCompTrees(compId); comps.pop(); while (comps.length) { const comp = comps.pop() as DesignComp; if (comp.compKey === "Group") { return true; } } return false; }, isStreamCardChild(compId: string) { if (compId == "root" || this.helper.isStreamCard(compId)) { return false; } const cards = this.controls.pageCtrl.streamCardIds; let n = cards.length; const ctrl = this.controls.pageCtrl; const compMap = ctrl.designData.compMap; while (n--) { const childs = compMap[cards[n]].children.default || []; if (childs.indexOf(compId) > -1) return true; } return false; }, findParentComp(compId: string): DesignComp | undefined { const comp = this.helper.findComp(compId); if (comp) return this.helper.findComp(this.controls.pageCtrl.compPids[compId]); }, findRootComp(): DesignComp | undefined { return this.controls.pageCtrl.rootPage; }, findCardAllChildren(index: number) { const ctrl = this.controls.pageCtrl; const cardId = ctrl.streamCardIds[index]; return ctrl.designData.compMap[cardId].children.default || ([] as string[]); }, getCompCard(compId: string) { const paths: DesignComp[] = this.helper.getCompTrees(compId); return paths[1]; }, getCompWorlParentPos(compId: string, vx: number, vy: number) { const paths: DesignComp[] = this.helper.getCompTrees(compId); const m = new Matrix(); let n = paths.length; let box = paths[1].$el.getBoundingClientRect(); const s = this.controls.editorCtrl.state.scale; m.translate((box.left - vx) / s, (box.top - vy) / s); for (let i = 2; i < n - 1; i++) { //card开始遍历 const m1 = new Matrix(); m1.setMatrixStr(paths[i].layout.transformMatrix || "matrix(1,0,0,1,0,0)"); m.append(m1); } return m; }, getCompTrees(compId: string) { const ctrl = this.controls.pageCtrl; const comps: DesignComp[] = []; const getParentComp = (compId: string) => { const comp = this.helper.findComp(compId); if (comp) { comps.unshift(comp); getParentComp(ctrl.compPids[comp.id]); } }; getParentComp(compId); return comps; }, createStyle(layout: Partial & { size: any[] }, comp: DesignComp) { const parentId = this.controls.pageCtrl.compPids[comp.id]; return createCompStyle(this, layout, comp, parentId); }, createViewStyles( layout: Partial & { size: any[] }, comp: DesignComp ) { return createViewStyles(this, layout); }, isCurrComp(compId: string) { const gizmo = this.controls.selectCtrl.gizmo; return ( gizmo.selectedIds.length == 1 && gizmo.selected[0].comp.id === compId ); }, isCustomChildComp(comp: DesignComp): boolean { const parentComp = this.helper.findParentComp(comp.id); if (!parentComp) return false; const i = parentComp.children.default?.findIndex((d) => d === comp.id) ?? -1; return i >= 0; }, isCompCanDelete(compId: string): boolean { const page = this.controls.pageCtrl; return ( this.helper.isStreamCardChild(compId) || (this.helper.isStreamCard(compId) && page.streamCardIds.length > 1) ); }, isShowSaveComp(comp: DesignComp): boolean { if (!this.helper.isStreamCardChild(comp.id)) return false; return true; }, clearUnusedComps(compMap: Record, rootId = "root") { const used = new Set(); const getUsedIds = (ids: string[]) => { ids.forEach((id) => { const comp = compMap[id]; if (!comp) return; used.add(id); getUsedIds(comp.children.default); }); return used; }; getUsedIds([rootId]); Object.keys(compMap).forEach((compId) => { if (!used.has(compId)) { delete compMap[compId]; } }); }, clearProjectUnusedComps(compMap: Record) { const used = new Set(); const getUsedIds = (ids: string[]) => { ids.forEach((id) => { const comp = compMap[id]; if (!comp) return; used.add(id); getUsedIds(comp.children.default || []); }); return used; }; getUsedIds(["root"]); const ctrl = this.controls.pageCtrl; const compScreenMap = ctrl.designData.compScreenMap; const keys = Object.keys(compScreenMap); keys.forEach((k) => { const card = compScreenMap[k]; card.forEach((c) => { c.children.forEach((item) => { const comp = compMap[item.id]; if (!comp) return; used.add(item.id); getUsedIds([item.id]); }); }); }); Object.keys(compMap).forEach((compId) => { if (!used.has(compId)) { delete compMap[compId]; } }); }, getPointOffsetWith(e: MouseEvent, dom: HTMLElement) { const domRect = dom.getBoundingClientRect(); return { x: e.clientX - domRect.left, y: e.clientY - domRect.top, }; }, getCardCompBound(compId: string) { const ctrl = this.controls.pageCtrl; const compMap = ctrl.designData.compMap; const c = compMap[compId]; const obj = new CompObject(c); const bound = obj.getBox(); return bound; }, extendStreamCard(streamCardId: string) { if (!streamCardId) return 0; const ctrl = this.controls.pageCtrl; const compMap = ctrl.designData.compMap; const card = compMap[streamCardId]; const size: any = card.layout.size.slice(0); if (this.controls.screenCtrl.isShortPage) { const h = this.controls.screenCtrl.getCurrScreenHeight(); size[1] = h; card.layout.setSize(size); return h; } const childs = card.children.default || []; let maxH = 0, n = childs.length; while (n--) { const c = childs[n]; const aabb = this.helper.getCardCompBound(c); maxH = Math.max(maxH, aabb.y + aabb.h); } maxH = this.helper.pxToDesignSize(maxH); if (childs.length < 1) { maxH = 200; } size[1] = maxH; card.layout.setSize(size); return maxH; }, updateGroups(compId: string) { const compTrees = this.helper.getCompTrees(compId); let n = compTrees.length; while (n > 0) { n--; if (compTrees[n].compKey == "Group") { // 计算高度 this.helper.updateGroupH(compTrees[n]); } } }, updateGroupH(comp: DesignComp) { const gizmo = this.controls.selectCtrl.gizmo; const childs = comp.children.default || []; let maxH = 0, n = childs.length; while (n--) { const c = childs[n]; const aabb = this.helper.getCardCompBound(c); maxH = Math.max(maxH, aabb.y + aabb.h); } maxH = this.helper.pxToDesignSize(maxH); const size: any = [comp.layout.size[0], maxH]; if (gizmo.selected[0].comp.id == comp.id) { gizmo.selected[0].setSize( this.helper.designSizeToPx(size[0]), this.helper.designSizeToPx(maxH) ); } else { comp.layout.setSize(size); } }, getCardNextPosY(cardId: string, itemWidth: number) { let yOffset = 0; if (cardId != this.controls.pageCtrl.state.currStreamCardId) { //const paths = this.helper.getCompTrees(cardId); const bound = this.helper.getCardCompBound(cardId); yOffset = bound.y + bound.h; } else { const currCard = this.helper.findComp(cardId) as DesignComp; //没有选中组件添加到当前卡片最后 const children = currCard.children.default || []; let prevCompIndex = -1; if (this.store.currCompId != "" && this.store.currCompId != "root") { prevCompIndex = children.indexOf(this.store.currCompId); } if (prevCompIndex != -1) { const bound = this.helper.getCardCompBound(children[prevCompIndex]); yOffset = bound.y + bound.h; } } const w = this.controls.screenCtrl.getCurrScreenWidth(); //添加组件到当前选中的组件下面 const xOffset: number = this.helper.designSizeToPx( w / 2.0 - (itemWidth || w) / 2 ); return { x: xOffset, y: yOffset }; }, getClientId() { let clientId = undefined; try { const userInfo = JSON.parse(localStorage.getItem("userInfo") || "{}"); clientId = userInfo._id || localStorage.getItem("clientId"); } catch (error) { console.error(error); } if (!clientId) { clientId = nanoid(); localStorage.setItem("clientId", clientId); } return clientId; }, loadImage(url) { return new Promise((res, rej) => { let t = setTimeout(() => { t = null as any; rej("下载超时"); }, 1000 * 10); const img = new Image(); img.onload = () => { res(img); if (t) clearTimeout(t); }; img.onerror = (e) => { rej("下载失败!"); }; img.src = url; }); }, });