import { cloneDeep, pick } from "lodash";
import { Exception, queenApi } from "queenjs";
import { EditorModule } from "..";
import { ScreenshotCtrl } from "../../controllers/ScreenshotCtrl";
import { CompObject } from "../../controllers/SelectCtrl/compObj";
import { DesignComp } from "../../objects/DesignTemp/DesignComp";
import { ICompKeys, Layout } from "../../typings";
import CompSave from "../../components/CompSave";
import { ObjsContainer } from "../../controllers/SelectCtrl/ObjsContainer";
import { getKeyThenIncreaseKey } from "ant-design-vue/lib/message";
import { Matrix } from "../../controllers/SelectCtrl/matrix";
import { nanoid } from "nanoid";
import { string } from "vue-types";
let ctrlcselected:string[] = [];
export const editActions = EditorModule.action({
pickComp(compId: string, selected = true) {
if (compId == "") {
//空的时候,就选择根页面
compId = "root";
}
const selectCardChild = (id: string) => {
const paths = this.helper.getCompTrees(id);
const cardChilds = paths[2];
if (cardChilds) {
this.actions.selectObjs([cardChilds.id]);
} else {
this.actions.selectObjs([]);
if (id != "root") {
this.store.setCurrComp(this.store.currStreamCardId);
}
}
};
if (this.store.currCompId == compId) {
return;
}
this.store.setCurrComp(compId);
if (selected) {
selectCardChild(compId);
}
},
// 通过点击添加组件到画布
async clickCompToDesign(compKey: ICompKeys, cb?: (comp: DesignComp) => void) {
if (!this.store.currStreamCardId) {
queenApi.messageError("请先选中一个卡片");
return;
}
//点击默认都创建一个容器
//创建容器
const isCreatCard =
compKey != "Text" &&
compKey != "Image" &&
compKey != "Rectage" &&
compKey != "Line" &&
compKey != "Arc" &&
compKey != "Triangle" &&
compKey != "Ellipse" &&
compKey != "Polygon" &&
compKey != "PolygonNormal" &&
compKey != "Curve";
let yOffset = 0;
if (
this.store.currCompId != this.store.currStreamCardId &&
!isCreatCard &&
this.store.currCompId != "root"
) {
const bound = this.helper.getCardCompBound(this.store.currCompId);
yOffset = bound.y + bound.h;
}
let currCard = this.store.currStreamCard;
if (isCreatCard) {
//先创建卡片
const currCardIndex =
this.store.streamCardIds.indexOf(this.store.currStreamCardId) + 1;
const compId = await this.store.insertDesignContent(
"Container",
currCardIndex
);
currCard = this.helper.findComp(compId) as DesignComp;
}
const compId = await this.store.insertCompContainer(compKey, currCard);
const addedComp = this.store.compMap[compId];
addedComp.layout.position = "absolute";
const currComp = this.helper.findComp(compId) as DesignComp;
cb?.(currComp);
//添加组件到当前选中的组件下面
let xOffset = this.helper.designSizeToPx(
375 - (currComp.layout.size?.[0] || 750) / 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.actions.pickComp(compId);
this.helper.extendStreamCard(currCard.id);
if (compKey == "Text") {
this.actions.textFocus(compId, true);
}
this.controls.cropCtrl.close();
},
// 通过点击添加组件到画布
async clickCompUserToDesign(id: string, isSys) {
if (!this.store.currStreamCardId) {
queenApi.messageError("请先选中一个卡片");
return;
}
const { result } = await this.https.getCompDetail(id, isSys);
//先创建卡片
// const currCardIndex = this.store.streamCardIds.indexOf(this.store.currStreamCardId) + 1;
// const cardId = await this.store.insertDesignContent(
// "Container",
// currCardIndex
// );
// const currCard = this.helper.findComp(cardId) as DesignComp;
const currCard = this.store.currStreamCard;
const comp = this.store.addUserCard(result);
const compId = comp.id;
const childIds = [...(currCard.children.default || [])];
childIds.push(compId);
currCard.children.default = childIds;
this.store.setCompPid(compId, currCard.id);
const addedComp = this.store.compMap[compId];
addedComp.layout.position = "absolute";
this.actions.initAddedCompPos(this.store.currCompId, compId, currCard.id);
this.actions.pickComp(compId);
},
initAddedCompPos(currId: string, addedId:string, cardId:string) {
let yOffset = 0;
if (
currId != this.store.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;
//添加组件到当前选中的组件下面
let xOffset = this.helper.designSizeToPx(
375 - (currComp.layout.size?.[0] || 750) / 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 currCardDom = this.store.currStreamCard.$el;
if (compKey == "CompCard") {
const { result } = await this.https.getCompDetail(data.id, data.isSys);
const comp = this.store.addUserCard(result);
const currCard = this.store.currStreamCard;
const compId = comp.id;
const childIds = [...(currCard.children.default || [])];
childIds.push(compId);
currCard.children.default = childIds;
const addedComp = this.store.compMap[compId];
addedComp.layout.position = "absolute";
this.store.setCompPid(compId, currCard.id);
this.actions.pickComp(compId);
} else {
await this.actions.addCompToDesign(compKey as any);
}
setTimeout(() => {
const cardPoints = this.helper.getPointOffsetWith(
event,
currCardDom
);
const { currComp } = this.store;
let selCtrl = this.controls.selectCtrl;
selCtrl.translate(
this.helper.designSizeToPx(375 - (currComp.layout.size?.[0] || 750) / 2),
cardPoints.y
);
this.helper.extendStreamCard(this.store.currStreamCardId);
if (compKey == "Text") {
this.actions.selectObjs([]);
this.actions.textFocus(currComp.id, true);
}
this.controls.cropCtrl.close();
}, 100);
},
async selectObjs(ids: string[], last = "") {
this.store.selected = ids;
this.store.selectId = ids.length > 1 ? Date.now() + "" : "";
this.store.lastSelected = last ? last : ( ids.length > 0 ? ids[ids.length-1] : "")
},
// 添加组件到画布
async addCompToDesign(compKey: ICompKeys, index?: number) {
if (!this.store.currStreamCardId) {
//必须选中一个streamCard
return;
}
if (compKey == "Container") {
// index = this.store.streamCardIds.indexOf(this.store.currStreamCardId) + 1;
const compId = await this.store.insertDesignContent(compKey, index);
this.actions.pickComp(compId);
return;
}
const compId = await this.store.insertCompContainer(
compKey,
this.store.currStreamCard
);
const addedComp = this.store.compMap[compId];
this.actions.setCompPositionFloat(addedComp);
this.actions.pickComp(compId);
},
// 切换当前组件
// pickComp(compId: string) {
// const { store, helper } = this;
// // 组合模式下,切换组件
// // if (store.currCompId && store.groupModeStatus) {
// // const enableGroupIds = helper
// // .findParentComp(compId)
// // ?.getChildIds() as string[];
// // const comps = helper.getCompTrees(compId);
// // while (comps.length) {
// // const comp = comps.pop() as DesignComp;
// // const index = store.groupIds.indexOf(comp.id);
// // if (index >= 0) {
// // const groupIds = [...store.groupIds];
// // groupIds.splice(index, 1);
// // store.setGroupIds(groupIds);
// // } else if (enableGroupIds.includes(comp.id)) {
// // store.groupIds.push(comp.id);
// // return;
// // }
// // }
// // return;
// // }
// // let nextCompId = compId;
// // if (this.store.isEditPage) {
// // const comps = this.helper.getCompTrees(compId);
// // nextCompId = comps[1].id;
// // }
// if (this.store.currCompId == compId) {
// return;
// }
// if (this.store.currComp.compKey == "Text") {
// this.store.setTextEditingState(false);
// }
// this.store.setCurrComp(compId);
// if (this.store.currCompId == this.store.currStreamCardId) {
// this.controls.transferCtrl.destroy();
// }
// },
// 切换到父组件
pickParentComp(compId: string) {
const parentComp = this.helper.findParentComp(compId);
parentComp && this.store.setCurrComp(parentComp.id);
},
ctrlc() {
// console.log("contrc ", this.store.selected);
ctrlcselected = this.store.selected.slice(0);
},
copyLastSelected() {
if (this.store.currCompId && this.store.currCompId != "root") {
ctrlcselected = [this.store.currCompId]
}
},
toogleGroup() {
if (this.store.selected.length > 1) {
this.actions.createGroupComps();
return;
}
if (this.store.selected.length == 1) {
const c = this.helper.findComp(this.store.selected[0]) as DesignComp;
if (c.compKey == "Group") {
this.actions.cancelGroupComps(c);
}
}
},
ctrlv() {
console.log("ctrlv ", this.store.selected);
if (ctrlcselected.length < 1) return;
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 = cloneDeep(cp);
cp1.id = nanoid();
this.store.compMap[cp1.id] = cp1;
this.store.setCompPid(cp1.id, c.id);
childs[index] = cp1.id;
deepCopy(cp);
})
}
}
ctrlcselected.forEach(c=>{
const cp = this.helper.findComp(c) as DesignComp;
const cp1 = cloneDeep(cp);
cp1.id = nanoid();
news.push(cp1.id);
this.store.compMap[cp1.id] = cp1;
this.store.setCompPid(cp1.id, this.store.currStreamCardId);
deepCopy(cp);
})
this.actions.addComps(news);
this.actions.selectObjs(news);
setTimeout(() => {
this.controls.selectCtrl.translate(20, 20);
}, 100);
},
addComps(ids:string[]) {
const childs = this.store.currStreamCard.children.default?.slice(0) || [];
childs.push(...ids);
this.store.currStreamCard.children.default = childs;
},
// 删除组件
removeSelectComps() {
const selected = this.store.selected.slice(0);
this.actions.selectObjs([]);
let n = selected.length;
while (n--) {
this.actions.removeComp(selected[n]);
}
},
// 删除组件
removeComp(compId: string) {
const paths = this.helper.getCompTrees(compId);
if (!paths[2]) return;
compId = paths[2].id;
if (this.helper.isCompCanDelete(compId)) {
if (this.helper.isStreamCard(compId)) {
this.actions.removeStreamCard(compId);
return;
}
const cardid = this.store.currStreamCardId;
if (compId === this.store.currCompId) {
this.store.setCurrComp(this.store.currStreamCardId);
}
this.store.deleteComp(compId);
this.helper.extendStreamCard(cardid);
this.actions.selectObjs([]);
}
},
async removeStreamCard(compId: string) {
await queenApi.showConfirm({ title: "删除", content: "确认删除当前内容?" });
// if (this.store.streamCardIds.length < 2) {
// queenApi.messageError("")
// return;
// }
let nextCard = this.store.currStreamCardId;
if (compId == this.store.currStreamCardId) {
const i = this.store.streamCardIds.indexOf(compId);
nextCard = this.store.streamCardIds[i + 1];
if (!nextCard) {
nextCard = this.store.streamCardIds[i - 1];
}
}
this.controls.selectCtrl.selecteObjs([]);
this.store.deleteComp(compId);
this.store.setCurrComp(nextCard);
},
// 移动组件顺序
moveComp(selIndex: number, targetIndex: number) {
if (selIndex === targetIndex) return;
this.store.moveComp(selIndex, targetIndex);
},
// 保存容器为组件
async saveAsComp(comp: DesignComp) {
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 data = {
title,
type,
thumbnail,
compMap: cloneDeep(this.store.designData.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("保存中");
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() {
try {
// 清除无用组件
this.helper.clearUnusedComps(this.store.designData.compMap);
// 封面截屏
if (!this.store.designData.thumbnail) {
await this.actions.updateThumbnailByScreenshot();
}
queenApi.showLoading("保存中");
await this.controls.uploader.uploadBlobs(this.store.designData);
if (this.store.isWk) {
await this.https[this.store.isEditPage ? "saveWkDesign" : "saveComp"](
this.store.designData
);
} else {
await this.https[this.store.isEditPage ? "saveDesign" : "saveComp"](
this.store.designData
);
}
queenApi.messageSuccess("保存成功");
} catch (error: any) {
throw Exception.error(error.toString());
} finally {
queenApi.hideLoading();
}
},
// 截屏保存封面
async updateThumbnailByScreenshot(autoSave?: boolean) {
try {
const rootComp = this.helper.findRootComp();
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);
this.store.setDesignThumbnail(thumbnail);
if (autoSave) {
await this.controls.uploader.uploadBlobs(this.store.designData);
await this.https[this.store.isEditPage ? "saveDesign" : "saveComp"](
pick(this.store.designData, ["_id", "thumbnail"])
);
queenApi.messageSuccess("保存成功");
}
} catch (error: any) {
throw Exception.error(error.toString());
} finally {
queenApi.hideLoading();
}
},
// 设置组件变换
setCompTransform(comp: DesignComp, transform: Layout["transform"]) {
if (!comp) return;
comp.layout.transform = transform;
console.log(comp);
},
// 设置组件变换
setCompTransformMatrix(comp: DesignComp, transformMatrix: string) {
if (!comp) return;
comp.layout.transformMatrix = transformMatrix;
},
// 设置组件浮动
setCompPositionFloat(comp: DesignComp) {
comp.layout.position = "absolute";
},
// 设置组件浮动
setCompPosition(comp: DesignComp) {
comp.layout.position =
comp.layout.position === "absolute" ? undefined : "absolute";
},
// 设置组件显示隐藏
setCompVisible(comp: DesignComp) {
comp.layout.visible = comp.layout.visible === false ? true : false;
},
// 清除组件变换
clearCompTransform(comp: DesignComp) {
comp.layout.margin = "";
comp.layout.transform = undefined;
},
// 设置组件锁定状态
setCompLock(comp: DesignComp) {
console.log(comp);
},
// 设置组件层级
setCompLayer(comp: DesignComp, offset: number) {
comp.layout.zIndex = Math.min(
Math.max((comp.layout.zIndex || 0) + offset, 0),
99
);
},
//横向对齐
setAlignX(flag: 0 | 1 | 2 | 3) {
console.log("alignX")
const selectCtrl = this.controls.selectCtrl;
if (this.store.selected.length == 1) {
const objc = selectCtrl.objContainer as ObjsContainer;
const box = objc.getBound();
switch(flag) {
case 0:
selectCtrl.translate(-box.left , 0);
break;
case 1:
selectCtrl.translate(-(box.center.x - 187.5) , 0);
break;
case 2:
selectCtrl.translate(375 - box.right, 0);
break;
}
return;
}
const anchorBox = this.helper.findComp(this.store.lastSelected);
if (!anchorBox) return;
const anchor = new CompObject(anchorBox);
const anchorRect = anchor.getBox();
const objc = selectCtrl.objContainer as ObjsContainer;
let min = 10000, max = -10000;
let step = 0;
if (flag == 3) {//Y轴均匀排布
objc.parent.children.forEach((c)=>{
const child = c as CompObject;
const r = child.getBox();
const x = r.x + r.w / 2.0;
if (x max ) max = x;
})
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 x = r.x + r.w / 2.0;
let minIndex = -1;
let minV = 10000;
for (let i=0; i{
const child = c as CompObject;
if (child.comp.id == this.store.lastSelected) 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;
}
})
objc.updateSize();
selectCtrl.upgateGizmoStyle();
},
setAlignY(flag: 0 | 1 | 2 | 3) {
const selectCtrl = this.controls.selectCtrl;
if (this.store.selected.length == 1) {
const objc = selectCtrl.objContainer as ObjsContainer;
const box = objc.getBound();
const card = new CompObject(this.store.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;
}
return;
}
const anchorBox = this.helper.findComp(this.store.lastSelected);
if (!anchorBox) return;
const anchor = new CompObject(anchorBox);
const anchorRect = anchor.getBox();
const objc = selectCtrl.objContainer as ObjsContainer;
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 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{
const child = c as CompObject;
if (child.comp.id == this.store.lastSelected) 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;
}
})
objc.updateSize();
selectCtrl.upgateGizmoStyle();
},
// 宽度铺满
fullCompWidth(comp: DesignComp) {
comp.layout.size || (comp.layout.size = []);
comp.layout.size[0] = 750;
},
//
setCompAlign(comp: DesignComp, align: string) {
comp.layout.alignSelf = align;
if (comp.layout.transform?.x) {
comp.layout.transform.x = 0;
}
},
// 开启组合模式
enableGroupMode() {
this.store.setGroupIds(
this.store.currCompId ? [this.store.currCompId] : []
);
this.store.setGroupMode(true);
},
// 关闭组合模式
async disableGroupMode() {
const groupId = await this.controls.transferCtrl.groupCtrl.combineGroup();
if (groupId) {
this.store.setCurrComp(groupId);
}
this.store.setGroupIds([]);
this.store.setGroupMode(false);
},
// 取消打组
cancelGroupComps(groupComp: DesignComp) {
const childs = groupComp.children.default || [];
const objC = this.controls.selectCtrl.objContainer as ObjsContainer;
const parentMtrx = objC.parent.worldTransform.clone();
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.transformMatrix = 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);
card.children.default = parentChilds;
this.actions.selectObjs([childs[0]]);
},
createGroupComps() {
const selectCtrl = this.controls.selectCtrl;
const Objc = this.controls.selectCtrl.objContainer as ObjsContainer;
const id = this.controls.compUICtrl.createCompId("Group");
const comp = this.helper.findComp(id) as DesignComp;
comp.layout.position = "absolute";
//先删除现有的节点
const sels = this.store.selected.slice(0);
const chils = this.store.currStreamCard.children.default || [];
const newChilds :any = [];
chils.forEach(c=>{
if (sels.indexOf(c) == -1) newChilds.push(c);
})
newChilds.push(id);
this.store.currStreamCard.children.default = newChilds;
//更新节点的新位置
Objc.parent.children.forEach(obj=>{
const cobj = obj as CompObject;
const comp = cobj.comp;
comp.layout.transformMatrix = cobj.localTransform.getMatrixStr();
})
//再添加新的节点
comp.layout.size = [this.helper.pxToDesignSize(Objc.width), this.helper.pxToDesignSize(Objc.height)];
comp.layout.transformMatrix = selectCtrl.transferStyle.matrix;
comp.children.default = sels;
this.actions.selectObjs([])
setTimeout(() => {
this.actions.pickComp(comp.id);
}, 0);
},
handleSelectMoving(key: string) {
if (this.store.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();
},
// 点击模板
async clickTplToDesign(record) {
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 } = frameData.result;
const designData = {
...this.store.designData,
compMap,
content,
desc,
thumbnail,
title,
};
this.actions.selectObjs([]);
this.store.setCurrComp("root");
this.store.setDesignData(designData);
this.store.currStreamCardId = this.store.streamCardIds[0];
},
});