project.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import type { ProjectInfo, Page, ReferLine } from "#/project";
  2. import type { ComponentType } from "@/components";
  3. import { defineStore } from "pinia";
  4. import componentAll from "@/components";
  5. import { ScreenFillEnum } from "@/enum/screenFillEnum";
  6. import { update, defaultsDeep } from "lodash";
  7. import { getNormalizedContainer } from "@/utils/common";
  8. type ProjectState = {
  9. projectInfo: ProjectInfo;
  10. activePageIndex: number;
  11. addCompData: {
  12. key: number;
  13. name: string;
  14. componentType: ComponentType;
  15. container: {
  16. style: Record<string, any>;
  17. props: Record<string, any>;
  18. };
  19. } | null;
  20. mode: "edit" | "player";
  21. selectedElementKeys: number[];
  22. };
  23. const defaultPage: Page = {
  24. name: "页面1",
  25. background: {
  26. type: "color",
  27. color: "#0B074BFF",
  28. image: "",
  29. fillType: "",
  30. },
  31. elements: [],
  32. referLines: [],
  33. };
  34. const CURRENT_PROJECT = "currentProject";
  35. export const useProjectStore = defineStore({
  36. id: "project",
  37. state: (): ProjectState => ({
  38. // 项目信息
  39. projectInfo: {
  40. name: "",
  41. description: "",
  42. sizeType: "",
  43. width: 0,
  44. height: 0,
  45. fillType: ScreenFillEnum.AUTO,
  46. pages: [{ ...defaultPage }],
  47. },
  48. // 当前编辑页面索引
  49. activePageIndex: 0,
  50. // 添加组件临时数据
  51. addCompData: null,
  52. // 视图模式
  53. mode: "edit",
  54. // 选中的元素
  55. selectedElementKeys: [],
  56. }),
  57. getters: {
  58. referLines(state) {
  59. return state.projectInfo.pages[state.activePageIndex].referLines;
  60. },
  61. elements(state) {
  62. return state.projectInfo.pages[state.activePageIndex].elements;
  63. },
  64. currentPage(state) {
  65. return state.projectInfo.pages[state.activePageIndex];
  66. },
  67. currentSelectedElements(state) {
  68. return state.projectInfo.pages[state.activePageIndex].elements.filter(
  69. (item) => state.selectedElementKeys.includes(item.key)
  70. );
  71. }
  72. },
  73. actions: {
  74. setProjectInfo(info: any) {
  75. Object.assign(this.projectInfo, info);
  76. localStorage.setItem(CURRENT_PROJECT, JSON.stringify(info));
  77. },
  78. getCurrentProjectInfo(): ProjectInfo | undefined {
  79. const info = JSON.parse(localStorage.getItem(CURRENT_PROJECT) || "");
  80. this.setProjectInfo(info as unknown as ProjectInfo);
  81. return info;
  82. },
  83. addReferLine(line: ReferLine) {
  84. this.projectInfo.pages[this.activePageIndex].referLines.push(line);
  85. },
  86. removeReferLine(key: number) {
  87. const index = this.referLines.findIndex((line) => line.key === key);
  88. index !== -1 &&
  89. this.projectInfo.pages[this.activePageIndex].referLines.splice(
  90. index,
  91. 1
  92. );
  93. },
  94. updateReferLine(line: ReferLine) {
  95. const index = this.referLines.findIndex((l) => l.key === line.key);
  96. if (index !== -1) {
  97. this.projectInfo.pages[this.activePageIndex].referLines[index] = line;
  98. }
  99. },
  100. // 添加组件
  101. async addElement(element: any) {
  102. this.addCompData = null;
  103. if (!element) return;
  104. const elements = this.projectInfo.pages[this.activePageIndex].elements;
  105. // 获取每个自定义组件暴露出来的属性
  106. const { defaultPropsValue } =
  107. (await componentAll[element.componentType as ComponentType]?.()) || {};
  108. const { width = 400, height = 260 } = defaultPropsValue?.container?.props || {};
  109. const { props: containerProps = {}, style = {} } = defaultPropsValue?.container || {};
  110. const index =
  111. elements.filter((item) => item.componentType === element.componentType)
  112. .length + 1;
  113. const { x, y } = element.container.props;
  114. const container = getNormalizedContainer({
  115. style,
  116. props: {
  117. ...containerProps,
  118. width,
  119. height,
  120. x: x - width / 2,
  121. y: y - height / 2,
  122. },
  123. });
  124. // 添加组件
  125. this.projectInfo.pages[this.activePageIndex].elements.push({
  126. ...defaultsDeep(element, defaultPropsValue),
  127. name: element.name + index,
  128. zIndex: elements.length + 1,
  129. visible: true,
  130. locked: false,
  131. container,
  132. });
  133. this.selectedElementKeys = [element.key];
  134. },
  135. // 更新组件
  136. updateElement(key: number, path: string, payload: any) {
  137. const element = this.projectInfo.pages[
  138. this.activePageIndex
  139. ].elements.find((item) => item.key === key);
  140. // 如果是锁定状态不能修改宽高 位置
  141. if (
  142. element &&
  143. element.locked &&
  144. [
  145. "container.props.width",
  146. "container.props.height",
  147. "container.props.x",
  148. "container.props.y",
  149. ].includes(path)
  150. )
  151. return;
  152. if (element) {
  153. update(element, path, () => payload);
  154. }
  155. },
  156. // 删除组件
  157. removeElement(key: number) {
  158. const index = this.projectInfo.pages[
  159. this.activePageIndex
  160. ].elements.findIndex((item) => item.key === key);
  161. if (index !== -1) {
  162. this.projectInfo.pages[this.activePageIndex].elements.splice(index, 1);
  163. }
  164. },
  165. // 设置临时添加组件数据
  166. setAddCompData(data: any) {
  167. this.addCompData = data;
  168. },
  169. // 清除临时添加组件数据
  170. clearAddCompData() {
  171. this.addCompData = null;
  172. },
  173. setMode(mode: "edit" | "player") {
  174. this.mode = mode;
  175. },
  176. // 设置选中的元素
  177. setSelectedElementKeys(keys: number[]) {
  178. this.selectedElementKeys = keys;
  179. },
  180. // 删除所有选中的元素
  181. clearAllSelectedElement() {
  182. this.selectedElementKeys = [];
  183. },
  184. // 设置当前页面背景
  185. setCurrentPageBackground(background: any) {
  186. this.projectInfo.pages[this.activePageIndex].background = background;
  187. },
  188. setFillType(fillType: ScreenFillEnum) {
  189. this.projectInfo.fillType = fillType;
  190. }
  191. },
  192. });