edit.tsx 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. import { cloneDeep, pick } from "lodash";
  2. import { Exception, queenApi } from "queenjs";
  3. import { EditorModule } from "..";
  4. import { ScreenshotCtrl } from "../../controllers/ScreenshotCtrl";
  5. import { CompObject } from "../../controllers/SelectCtrl/compObj";
  6. import { DesignComp } from "../../objects/DesignTemp/DesignComp";
  7. import { ICompKeys, Layout } from "../../typings";
  8. import CompSave from "../../components/CompSave";
  9. import { ObjsContainer } from "../../controllers/SelectCtrl/ObjsContainer";
  10. import { getKeyThenIncreaseKey } from "ant-design-vue/lib/message";
  11. import { Matrix } from "../../controllers/SelectCtrl/matrix";
  12. import { nanoid } from "nanoid";
  13. import { string } from "vue-types";
  14. let ctrlcselected:string[] = [];
  15. export const editActions = EditorModule.action({
  16. pickComp(compId: string, selected = true) {
  17. if (compId == "") {
  18. //空的时候,就选择根页面
  19. compId = "root";
  20. }
  21. const selectCardChild = (id: string) => {
  22. const paths = this.helper.getCompTrees(id);
  23. const cardChilds = paths[2];
  24. if (cardChilds) {
  25. this.actions.selectObjs([cardChilds.id]);
  26. } else {
  27. this.actions.selectObjs([]);
  28. if (id != "root") {
  29. this.store.setCurrComp(this.store.currStreamCardId);
  30. }
  31. }
  32. };
  33. if (this.store.currCompId == compId) {
  34. return;
  35. }
  36. this.store.setCurrComp(compId);
  37. if (selected) {
  38. selectCardChild(compId);
  39. }
  40. },
  41. // 通过点击添加组件到画布
  42. async clickCompToDesign(compKey: ICompKeys, cb?: (comp: DesignComp) => void) {
  43. if (!this.store.currStreamCardId) {
  44. queenApi.messageError("请先选中一个卡片");
  45. return;
  46. }
  47. //点击默认都创建一个容器
  48. //创建容器
  49. const isCreatCard =
  50. compKey != "Text" &&
  51. compKey != "Image" &&
  52. compKey != "Rectage" &&
  53. compKey != "Line" &&
  54. compKey != "Arc" &&
  55. compKey != "Triangle" &&
  56. compKey != "Ellipse" &&
  57. compKey != "Polygon" &&
  58. compKey != "PolygonNormal" &&
  59. compKey != "Curve";
  60. let yOffset = 0;
  61. if (
  62. this.store.currCompId != this.store.currStreamCardId &&
  63. !isCreatCard &&
  64. this.store.currCompId != "root"
  65. ) {
  66. const bound = this.helper.getCardCompBound(this.store.currCompId);
  67. yOffset = bound.y + bound.h;
  68. }
  69. let currCard = this.store.currStreamCard;
  70. if (isCreatCard) {
  71. //先创建卡片
  72. const currCardIndex =
  73. this.store.streamCardIds.indexOf(this.store.currStreamCardId) + 1;
  74. const compId = await this.store.insertDesignContent(
  75. "Container",
  76. currCardIndex
  77. );
  78. currCard = this.helper.findComp(compId) as DesignComp;
  79. }
  80. const compId = await this.store.insertCompContainer(compKey, currCard);
  81. const addedComp = this.store.compMap[compId];
  82. addedComp.layout.position = "absolute";
  83. const currComp = this.helper.findComp(compId) as DesignComp;
  84. cb?.(currComp);
  85. //添加组件到当前选中的组件下面
  86. let xOffset = this.helper.designSizeToPx(
  87. 375 - (currComp.layout.size?.[0] || 750) / 2
  88. );
  89. const obj = new CompObject(currComp);
  90. //没有选中组件添加到当前卡片最后
  91. const children = currCard.children.default || [];
  92. if (yOffset == 0 && children.length >= 2) {
  93. const prevCompIndex = children.indexOf(compId) - 1;
  94. const bound = this.helper.getCardCompBound(children[prevCompIndex]);
  95. yOffset = bound.y + bound.h;
  96. }
  97. obj.worldTransform.translate(xOffset, yOffset);
  98. currComp.layout.transformMatrix = obj.worldTransform.getMatrixStr();
  99. this.actions.pickComp(compId);
  100. this.helper.extendStreamCard(currCard.id);
  101. if (compKey == "Text") {
  102. this.actions.textFocus(compId, true);
  103. }
  104. this.controls.cropCtrl.close();
  105. },
  106. // 通过点击添加组件到画布
  107. async clickCompUserToDesign(id: string, isSys) {
  108. if (!this.store.currStreamCardId) {
  109. queenApi.messageError("请先选中一个卡片");
  110. return;
  111. }
  112. const { result } = await this.https.getCompDetail(id, isSys);
  113. //先创建卡片
  114. // const currCardIndex = this.store.streamCardIds.indexOf(this.store.currStreamCardId) + 1;
  115. // const cardId = await this.store.insertDesignContent(
  116. // "Container",
  117. // currCardIndex
  118. // );
  119. // const currCard = this.helper.findComp(cardId) as DesignComp;
  120. const currCard = this.store.currStreamCard;
  121. const comp = this.store.addUserCard(result);
  122. const compId = comp.id;
  123. const childIds = [...(currCard.children.default || [])];
  124. childIds.push(compId);
  125. currCard.children.default = childIds;
  126. this.store.setCompPid(compId, currCard.id);
  127. const addedComp = this.store.compMap[compId];
  128. addedComp.layout.position = "absolute";
  129. this.actions.initAddedCompPos(this.store.currCompId, compId, currCard.id);
  130. this.actions.pickComp(compId);
  131. },
  132. initAddedCompPos(currId: string, addedId:string, cardId:string) {
  133. let yOffset = 0;
  134. if (
  135. currId != this.store.currStreamCardId &&
  136. currId != "root"
  137. ) {
  138. const paths = this.helper.getCompTrees(currId)
  139. const bound = this.helper.getCardCompBound(paths[2].id);
  140. yOffset = bound.y + bound.h;
  141. }
  142. const currComp = this.helper.findComp(addedId) as DesignComp;
  143. //添加组件到当前选中的组件下面
  144. let xOffset = this.helper.designSizeToPx(
  145. 375 - (currComp.layout.size?.[0] || 750) / 2
  146. );
  147. const obj = new CompObject(currComp);
  148. const currCard = this.helper.findComp(cardId) as DesignComp;
  149. //没有选中组件添加到当前卡片最后
  150. const children = currCard.children.default || [];
  151. if (yOffset == 0 && children.length >= 2) {
  152. const prevCompIndex = children.indexOf(addedId) - 1;
  153. const bound = this.helper.getCardCompBound(children[prevCompIndex]);
  154. yOffset = bound.y + bound.h;
  155. }
  156. obj.worldTransform.translate(xOffset, yOffset);
  157. currComp.layout.transformMatrix = obj.worldTransform.getMatrixStr();
  158. this.helper.extendStreamCard(currCard.id);
  159. this.controls.cropCtrl.close();
  160. },
  161. // 通过拖拽添加组件到画布
  162. async dragCompToDesign(event: MouseEvent, compKey: string, data:any) {
  163. const currCardDom = this.store.currStreamCard.$el;
  164. if (compKey == "CompCard") {
  165. const { result } = await this.https.getCompDetail(data.id, data.isSys);
  166. const comp = this.store.addUserCard(result);
  167. const currCard = this.store.currStreamCard;
  168. const compId = comp.id;
  169. const childIds = [...(currCard.children.default || [])];
  170. childIds.push(compId);
  171. currCard.children.default = childIds;
  172. const addedComp = this.store.compMap[compId];
  173. addedComp.layout.position = "absolute";
  174. this.store.setCompPid(compId, currCard.id);
  175. this.actions.pickComp(compId);
  176. } else {
  177. await this.actions.addCompToDesign(compKey as any);
  178. }
  179. setTimeout(() => {
  180. const cardPoints = this.helper.getPointOffsetWith(
  181. event,
  182. currCardDom
  183. );
  184. const { currComp } = this.store;
  185. let selCtrl = this.controls.selectCtrl;
  186. selCtrl.translate(
  187. this.helper.designSizeToPx(375 - (currComp.layout.size?.[0] || 750) / 2),
  188. cardPoints.y
  189. );
  190. this.helper.extendStreamCard(this.store.currStreamCardId);
  191. if (compKey == "Text") {
  192. this.actions.selectObjs([]);
  193. this.actions.textFocus(currComp.id, true);
  194. }
  195. this.controls.cropCtrl.close();
  196. }, 100);
  197. },
  198. async selectObjs(ids: string[], last = "") {
  199. this.store.selected = ids;
  200. this.store.selectId = ids.length > 1 ? Date.now() + "" : "";
  201. this.store.lastSelected = last ? last : ( ids.length > 0 ? ids[ids.length-1] : "")
  202. },
  203. // 添加组件到画布
  204. async addCompToDesign(compKey: ICompKeys, index?: number) {
  205. if (!this.store.currStreamCardId) {
  206. //必须选中一个streamCard
  207. return;
  208. }
  209. if (compKey == "Container") {
  210. // index = this.store.streamCardIds.indexOf(this.store.currStreamCardId) + 1;
  211. const compId = await this.store.insertDesignContent(compKey, index);
  212. this.actions.pickComp(compId);
  213. return;
  214. }
  215. const compId = await this.store.insertCompContainer(
  216. compKey,
  217. this.store.currStreamCard
  218. );
  219. const addedComp = this.store.compMap[compId];
  220. this.actions.setCompPositionFloat(addedComp);
  221. this.actions.pickComp(compId);
  222. },
  223. // 切换当前组件
  224. // pickComp(compId: string) {
  225. // const { store, helper } = this;
  226. // // 组合模式下,切换组件
  227. // // if (store.currCompId && store.groupModeStatus) {
  228. // // const enableGroupIds = helper
  229. // // .findParentComp(compId)
  230. // // ?.getChildIds() as string[];
  231. // // const comps = helper.getCompTrees(compId);
  232. // // while (comps.length) {
  233. // // const comp = comps.pop() as DesignComp;
  234. // // const index = store.groupIds.indexOf(comp.id);
  235. // // if (index >= 0) {
  236. // // const groupIds = [...store.groupIds];
  237. // // groupIds.splice(index, 1);
  238. // // store.setGroupIds(groupIds);
  239. // // } else if (enableGroupIds.includes(comp.id)) {
  240. // // store.groupIds.push(comp.id);
  241. // // return;
  242. // // }
  243. // // }
  244. // // return;
  245. // // }
  246. // // let nextCompId = compId;
  247. // // if (this.store.isEditPage) {
  248. // // const comps = this.helper.getCompTrees(compId);
  249. // // nextCompId = comps[1].id;
  250. // // }
  251. // if (this.store.currCompId == compId) {
  252. // return;
  253. // }
  254. // if (this.store.currComp.compKey == "Text") {
  255. // this.store.setTextEditingState(false);
  256. // }
  257. // this.store.setCurrComp(compId);
  258. // if (this.store.currCompId == this.store.currStreamCardId) {
  259. // this.controls.transferCtrl.destroy();
  260. // }
  261. // },
  262. // 切换到父组件
  263. pickParentComp(compId: string) {
  264. const parentComp = this.helper.findParentComp(compId);
  265. parentComp && this.store.setCurrComp(parentComp.id);
  266. },
  267. ctrlc() {
  268. // console.log("contrc ", this.store.selected);
  269. ctrlcselected = this.store.selected.slice(0);
  270. },
  271. copyLastSelected() {
  272. if (this.store.currCompId && this.store.currCompId != "root") {
  273. ctrlcselected = [this.store.currCompId]
  274. }
  275. },
  276. toogleGroup() {
  277. if (this.store.selected.length > 1) {
  278. this.actions.createGroupComps();
  279. return;
  280. }
  281. if (this.store.selected.length == 1) {
  282. const c = this.helper.findComp(this.store.selected[0]) as DesignComp;
  283. if (c.compKey == "Group") {
  284. this.actions.cancelGroupComps(c);
  285. }
  286. }
  287. },
  288. ctrlv() {
  289. console.log("ctrlv ", this.store.selected);
  290. if (ctrlcselected.length < 1) return;
  291. const news :string[] = [];
  292. const deepCopy = (c:DesignComp) => {
  293. const childs = c.children.default || [];
  294. if (childs.length > 0 ) {
  295. childs.forEach((id, index)=>{
  296. const cp = this.helper.findComp(id) as DesignComp;
  297. const cp1 = cloneDeep(cp);
  298. cp1.id = nanoid();
  299. this.store.compMap[cp1.id] = cp1;
  300. this.store.setCompPid(cp1.id, c.id);
  301. childs[index] = cp1.id;
  302. deepCopy(cp);
  303. })
  304. }
  305. }
  306. ctrlcselected.forEach(c=>{
  307. const cp = this.helper.findComp(c) as DesignComp;
  308. const cp1 = cloneDeep(cp);
  309. cp1.id = nanoid();
  310. news.push(cp1.id);
  311. this.store.compMap[cp1.id] = cp1;
  312. this.store.setCompPid(cp1.id, this.store.currStreamCardId);
  313. deepCopy(cp);
  314. })
  315. this.actions.addComps(news);
  316. this.actions.selectObjs(news);
  317. setTimeout(() => {
  318. this.controls.selectCtrl.translate(20, 20);
  319. }, 100);
  320. },
  321. addComps(ids:string[]) {
  322. const childs = this.store.currStreamCard.children.default?.slice(0) || [];
  323. childs.push(...ids);
  324. this.store.currStreamCard.children.default = childs;
  325. },
  326. // 删除组件
  327. removeSelectComps() {
  328. const selected = this.store.selected.slice(0);
  329. this.actions.selectObjs([]);
  330. let n = selected.length;
  331. while (n--) {
  332. this.actions.removeComp(selected[n]);
  333. }
  334. },
  335. // 删除组件
  336. removeComp(compId: string) {
  337. const paths = this.helper.getCompTrees(compId);
  338. if (!paths[2]) return;
  339. compId = paths[2].id;
  340. if (this.helper.isCompCanDelete(compId)) {
  341. if (this.helper.isStreamCard(compId)) {
  342. this.actions.removeStreamCard(compId);
  343. return;
  344. }
  345. const cardid = this.store.currStreamCardId;
  346. if (compId === this.store.currCompId) {
  347. this.store.setCurrComp(this.store.currStreamCardId);
  348. }
  349. this.store.deleteComp(compId);
  350. this.helper.extendStreamCard(cardid);
  351. this.actions.selectObjs([]);
  352. }
  353. },
  354. async removeStreamCard(compId: string) {
  355. await queenApi.showConfirm({ title: "删除", content: "确认删除当前内容?" });
  356. // if (this.store.streamCardIds.length < 2) {
  357. // queenApi.messageError("")
  358. // return;
  359. // }
  360. let nextCard = this.store.currStreamCardId;
  361. if (compId == this.store.currStreamCardId) {
  362. const i = this.store.streamCardIds.indexOf(compId);
  363. nextCard = this.store.streamCardIds[i + 1];
  364. if (!nextCard) {
  365. nextCard = this.store.streamCardIds[i - 1];
  366. }
  367. }
  368. this.controls.selectCtrl.selecteObjs([]);
  369. this.store.deleteComp(compId);
  370. this.store.setCurrComp(nextCard);
  371. },
  372. // 移动组件顺序
  373. moveComp(selIndex: number, targetIndex: number) {
  374. if (selIndex === targetIndex) return;
  375. this.store.moveComp(selIndex, targetIndex);
  376. },
  377. // 保存容器为组件
  378. async saveAsComp(comp: DesignComp) {
  379. try {
  380. const CompSave = this.components.CompSave as any;
  381. let title = "";
  382. let type = "comp";
  383. try {
  384. const ret:any = await queenApi.dialog(<CompSave />, {width:"300px", title: "保存到我的"});
  385. if (!ret) {
  386. return;
  387. }
  388. title = ret.title;
  389. type = ret.type;
  390. } catch (error) {
  391. return;
  392. }
  393. console.log( title, type);
  394. // 组件封面
  395. const blob = await new ScreenshotCtrl().snap({
  396. element: comp.$el,
  397. });
  398. const thumbnail = URL.createObjectURL(blob);
  399. // const title = await queenApi.showInput({
  400. // title: "保存到我的",
  401. // defaultValue: this.controls.compUICtrl.state.components.get(
  402. // comp.compKey
  403. // )?.name,
  404. // });
  405. const data = {
  406. title,
  407. type,
  408. thumbnail,
  409. compMap: cloneDeep(this.store.designData.compMap),
  410. };
  411. this.helper.clearUnusedComps(data.compMap, comp.id);
  412. data.compMap.root = data.compMap[comp.id];
  413. data.compMap.root.id = "root";
  414. //清除平移距离
  415. const mtx = Matrix.createFromMatrixStr(data.compMap.root.layout.transformMatrix as string);
  416. mtx.tx = 0;
  417. mtx.ty = 0;
  418. data.compMap.root.layout.transformMatrix = mtx.getMatrixStr();
  419. delete data.compMap[comp.id];
  420. queenApi.showLoading("保存中");
  421. await this.controls.uploader.uploadBlobs(data);
  422. await this.https.createComp(data);
  423. queenApi.messageSuccess("保存成功");
  424. } catch (error: any) {
  425. throw Exception.error(error.toString());
  426. } finally {
  427. queenApi.hideLoading();
  428. }
  429. },
  430. // 保存项目
  431. async saveDesign() {
  432. try {
  433. // 清除无用组件
  434. this.helper.clearUnusedComps(this.store.designData.compMap);
  435. // 封面截屏
  436. if (!this.store.designData.thumbnail) {
  437. await this.actions.updateThumbnailByScreenshot();
  438. }
  439. queenApi.showLoading("保存中");
  440. await this.controls.uploader.uploadBlobs(this.store.designData);
  441. if (this.store.isWk) {
  442. await this.https[this.store.isEditPage ? "saveWkDesign" : "saveComp"](
  443. this.store.designData
  444. );
  445. } else {
  446. await this.https[this.store.isEditPage ? "saveDesign" : "saveComp"](
  447. this.store.designData
  448. );
  449. }
  450. queenApi.messageSuccess("保存成功");
  451. } catch (error: any) {
  452. throw Exception.error(error.toString());
  453. } finally {
  454. queenApi.hideLoading();
  455. }
  456. },
  457. // 截屏保存封面
  458. async updateThumbnailByScreenshot(autoSave?: boolean) {
  459. try {
  460. const rootComp = this.helper.findRootComp();
  461. if (!rootComp) return;
  462. queenApi.showLoading("截屏中");
  463. const blob = await new ScreenshotCtrl().snap({
  464. element: rootComp.$el,
  465. ratio: this.store.isEditComp ? 0 : 1,
  466. });
  467. const thumbnail = URL.createObjectURL(blob);
  468. this.store.setDesignThumbnail(thumbnail);
  469. if (autoSave) {
  470. await this.controls.uploader.uploadBlobs(this.store.designData);
  471. await this.https[this.store.isEditPage ? "saveDesign" : "saveComp"](
  472. pick(this.store.designData, ["_id", "thumbnail"])
  473. );
  474. queenApi.messageSuccess("保存成功");
  475. }
  476. } catch (error: any) {
  477. throw Exception.error(error.toString());
  478. } finally {
  479. queenApi.hideLoading();
  480. }
  481. },
  482. // 设置组件变换
  483. setCompTransform(comp: DesignComp, transform: Layout["transform"]) {
  484. if (!comp) return;
  485. comp.layout.transform = transform;
  486. console.log(comp);
  487. },
  488. // 设置组件变换
  489. setCompTransformMatrix(comp: DesignComp, transformMatrix: string) {
  490. if (!comp) return;
  491. comp.layout.transformMatrix = transformMatrix;
  492. },
  493. // 设置组件浮动
  494. setCompPositionFloat(comp: DesignComp) {
  495. comp.layout.position = "absolute";
  496. },
  497. // 设置组件浮动
  498. setCompPosition(comp: DesignComp) {
  499. comp.layout.position =
  500. comp.layout.position === "absolute" ? undefined : "absolute";
  501. },
  502. // 设置组件显示隐藏
  503. setCompVisible(comp: DesignComp) {
  504. comp.layout.visible = comp.layout.visible === false ? true : false;
  505. },
  506. // 清除组件变换
  507. clearCompTransform(comp: DesignComp) {
  508. comp.layout.margin = "";
  509. comp.layout.transform = undefined;
  510. },
  511. // 设置组件锁定状态
  512. setCompLock(comp: DesignComp) {
  513. console.log(comp);
  514. },
  515. // 设置组件层级
  516. setCompLayer(comp: DesignComp, offset: number) {
  517. comp.layout.zIndex = Math.min(
  518. Math.max((comp.layout.zIndex || 0) + offset, 0),
  519. 99
  520. );
  521. },
  522. //横向对齐
  523. setAlignX(flag: 0 | 1 | 2 | 3) {
  524. console.log("alignX")
  525. const selectCtrl = this.controls.selectCtrl;
  526. if (this.store.selected.length == 1) {
  527. const objc = selectCtrl.objContainer as ObjsContainer;
  528. const box = objc.getBound();
  529. switch(flag) {
  530. case 0:
  531. selectCtrl.translate(-box.left , 0);
  532. break;
  533. case 1:
  534. selectCtrl.translate(-(box.center.x - 187.5) , 0);
  535. break;
  536. case 2:
  537. selectCtrl.translate(375 - box.right, 0);
  538. break;
  539. }
  540. return;
  541. }
  542. const anchorBox = this.helper.findComp(this.store.lastSelected);
  543. if (!anchorBox) return;
  544. const anchor = new CompObject(anchorBox);
  545. const anchorRect = anchor.getBox();
  546. const objc = selectCtrl.objContainer as ObjsContainer;
  547. let min = 10000, max = -10000;
  548. let step = 0;
  549. if (flag == 3) {//Y轴均匀排布
  550. objc.parent.children.forEach((c)=>{
  551. const child = c as CompObject;
  552. const r = child.getBox();
  553. const x = r.x + r.w / 2.0;
  554. if (x <min) min = x;
  555. if (x >max ) max = x;
  556. })
  557. const stepCount = objc.parent.children.length;
  558. step = (max - min) / (stepCount - 1);
  559. const stepIndexMap:any = {};
  560. objc.parent.children.forEach((c)=>{
  561. const child = c as CompObject;
  562. const r = child.getBox();
  563. const x = r.x + r.w / 2.0;
  564. let minIndex = -1;
  565. let minV = 10000;
  566. for (let i=0; i<stepCount; i++) {
  567. const ty = i*step + min;
  568. if ( Math.abs(x - ty) < minV && !stepIndexMap[i]) {
  569. minV = Math.abs(x - ty);
  570. minIndex = i;
  571. }
  572. }
  573. stepIndexMap[minIndex] = true;
  574. child.translate((minIndex*step + min) - x, 0);
  575. })
  576. objc.updateSize();
  577. selectCtrl.upgateGizmoStyle();
  578. return;
  579. }
  580. objc.parent.children.forEach((c)=>{
  581. const child = c as CompObject;
  582. if (child.comp.id == this.store.lastSelected) return;
  583. const r = child.getBox();
  584. switch(flag) {
  585. case 0:
  586. child.translate(anchorRect.x -r.x, 0);
  587. break;
  588. case 1:
  589. child.translate(anchorRect.x + anchorRect.w / 2.0 - (r.x + r.w/2.0), 0);
  590. break;
  591. case 2:
  592. child.translate(anchorRect.x + anchorRect.w - (r.x + r.w), 0);
  593. break;
  594. }
  595. })
  596. objc.updateSize();
  597. selectCtrl.upgateGizmoStyle();
  598. },
  599. setAlignY(flag: 0 | 1 | 2 | 3) {
  600. const selectCtrl = this.controls.selectCtrl;
  601. if (this.store.selected.length == 1) {
  602. const objc = selectCtrl.objContainer as ObjsContainer;
  603. const box = objc.getBound();
  604. const card = new CompObject(this.store.currStreamCard);
  605. const cardBox = card.getBox();
  606. switch(flag) {
  607. case 0:
  608. selectCtrl.translate(0, -box.top);
  609. break;
  610. case 1:
  611. selectCtrl.translate(0 , -(box.center.y - cardBox.h / 2.0));
  612. break;
  613. case 2:
  614. selectCtrl.translate(0, cardBox.h - box.bottom);
  615. break;
  616. }
  617. return;
  618. }
  619. const anchorBox = this.helper.findComp(this.store.lastSelected);
  620. if (!anchorBox) return;
  621. const anchor = new CompObject(anchorBox);
  622. const anchorRect = anchor.getBox();
  623. const objc = selectCtrl.objContainer as ObjsContainer;
  624. let min = 10000;
  625. let max = -10000;
  626. let step = 0;
  627. if (flag == 3) {//Y轴均匀排布
  628. objc.parent.children.forEach((c)=>{
  629. const child = c as CompObject;
  630. const r = child.getBox();
  631. const y = r.y + r.h / 2.0;
  632. if (y <min) min = y;
  633. if (y >max ) max = y;
  634. })
  635. const stepCount = objc.parent.children.length;
  636. step = (max - min) / (stepCount - 1);
  637. const stepIndexMap:any = {};
  638. objc.parent.children.forEach((c)=>{
  639. const child = c as CompObject;
  640. const r = child.getBox();
  641. const y = r.y + r.h / 2.0;
  642. let minIndex = -1;
  643. let minV = 10000;
  644. for (let i=0; i<stepCount; i++) {
  645. const ty = i*step + min;
  646. if ( Math.abs(y - ty) < minV && !stepIndexMap[i]) {
  647. minV = Math.abs(y - ty);
  648. minIndex = i;
  649. }
  650. }
  651. stepIndexMap[minIndex] = true;
  652. child.translate(0, (minIndex*step + min) - y);
  653. })
  654. objc.updateSize();
  655. selectCtrl.upgateGizmoStyle();
  656. return;
  657. }
  658. objc.parent.children.forEach((c)=>{
  659. const child = c as CompObject;
  660. if (child.comp.id == this.store.lastSelected) return;
  661. const r = child.getBox();
  662. switch(flag) {
  663. case 0:
  664. child.translate(0, anchorRect.y -r.y);
  665. break;
  666. case 1:
  667. child.translate(0, anchorRect.y + anchorRect.h / 2.0 - (r.y + r.h /2.0));
  668. break;
  669. case 2:
  670. child.translate(0, anchorRect.y + anchorRect.h - (r.y + r.h));
  671. break;
  672. }
  673. })
  674. objc.updateSize();
  675. selectCtrl.upgateGizmoStyle();
  676. },
  677. // 宽度铺满
  678. fullCompWidth(comp: DesignComp) {
  679. comp.layout.size || (comp.layout.size = []);
  680. comp.layout.size[0] = 750;
  681. },
  682. //
  683. setCompAlign(comp: DesignComp, align: string) {
  684. comp.layout.alignSelf = align;
  685. if (comp.layout.transform?.x) {
  686. comp.layout.transform.x = 0;
  687. }
  688. },
  689. // 开启组合模式
  690. enableGroupMode() {
  691. this.store.setGroupIds(
  692. this.store.currCompId ? [this.store.currCompId] : []
  693. );
  694. this.store.setGroupMode(true);
  695. },
  696. // 关闭组合模式
  697. async disableGroupMode() {
  698. const groupId = await this.controls.transferCtrl.groupCtrl.combineGroup();
  699. if (groupId) {
  700. this.store.setCurrComp(groupId);
  701. }
  702. this.store.setGroupIds([]);
  703. this.store.setGroupMode(false);
  704. },
  705. // 取消打组
  706. cancelGroupComps(groupComp: DesignComp) {
  707. const childs = groupComp.children.default || [];
  708. const objC = this.controls.selectCtrl.objContainer as ObjsContainer;
  709. const parentMtrx = objC.parent.worldTransform.clone();
  710. childs.forEach(o=>{
  711. const obj = this.helper.findComp(o) as DesignComp;
  712. const mxt = Matrix.createFromMatrixStr(obj.layout.transformMatrix as string);
  713. mxt.prepend(parentMtrx);
  714. obj.layout.transformMatrix = mxt.getMatrixStr();
  715. })
  716. const paths = this.helper.getCompTrees(groupComp.id)
  717. const card = paths[1];
  718. const parentChilds = (card.children.default || []).filter(item=>item != groupComp.id);
  719. parentChilds.push(...childs);
  720. card.children.default = parentChilds;
  721. this.actions.selectObjs([childs[0]]);
  722. },
  723. createGroupComps() {
  724. const selectCtrl = this.controls.selectCtrl;
  725. const Objc = this.controls.selectCtrl.objContainer as ObjsContainer;
  726. const id = this.controls.compUICtrl.createCompId("Group");
  727. const comp = this.helper.findComp(id) as DesignComp;
  728. comp.layout.position = "absolute";
  729. //先删除现有的节点
  730. const sels = this.store.selected.slice(0);
  731. const chils = this.store.currStreamCard.children.default || [];
  732. const newChilds :any = [];
  733. chils.forEach(c=>{
  734. if (sels.indexOf(c) == -1) newChilds.push(c);
  735. })
  736. newChilds.push(id);
  737. this.store.currStreamCard.children.default = newChilds;
  738. //更新节点的新位置
  739. Objc.parent.children.forEach(obj=>{
  740. const cobj = obj as CompObject;
  741. const comp = cobj.comp;
  742. comp.layout.transformMatrix = cobj.localTransform.getMatrixStr();
  743. })
  744. //再添加新的节点
  745. comp.layout.size = [this.helper.pxToDesignSize(Objc.width), this.helper.pxToDesignSize(Objc.height)];
  746. comp.layout.transformMatrix = selectCtrl.transferStyle.matrix;
  747. comp.children.default = sels;
  748. this.actions.selectObjs([])
  749. setTimeout(() => {
  750. this.actions.pickComp(comp.id);
  751. }, 0);
  752. },
  753. handleSelectMoving(key: string) {
  754. if (this.store.selected.length < 1) return;
  755. let x = 0,
  756. y = 0;
  757. switch (key) {
  758. case "left":
  759. x = -1;
  760. break;
  761. case "right":
  762. x = 1;
  763. break;
  764. case "up":
  765. y = -1;
  766. break;
  767. case "down":
  768. y = 1;
  769. break;
  770. }
  771. this.controls.selectCtrl.translate(x * 0.5, y * 0.5);
  772. this.controls.selectCtrl.assistCtrl?.flashDrawCardDists();
  773. },
  774. // 点击模板
  775. async clickTplToDesign(record) {
  776. const res = await queenApi.showConfirm({
  777. title: "",
  778. content: "要替换正在编辑的内容?",
  779. });
  780. if (!res) return;
  781. const frameData = await this.https.getDesignDetail(record._id, {
  782. isSys: true,
  783. });
  784. const { compMap, content, desc, thumbnail, title } = frameData.result;
  785. const designData = {
  786. ...this.store.designData,
  787. compMap,
  788. content,
  789. desc,
  790. thumbnail,
  791. title,
  792. };
  793. this.actions.selectObjs([]);
  794. this.store.setCurrComp("root");
  795. this.store.setDesignData(designData);
  796. this.store.currStreamCardId = this.store.streamCardIds[0];
  797. },
  798. });