appModel.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { Cell, EventArgs, Graph } from "@antv/x6";
  2. import { useEffect, useRef, useState } from "react";
  3. import { message } from "antd";
  4. import brushImg from "@/assets/image/brush.svg"
  5. import { cellStyle } from '@/types'
  6. interface PageSettings {
  7. // 背景颜色
  8. backgroundColor: string;
  9. // 宽
  10. width: number;
  11. // 高
  12. height: number;
  13. // 显示网格
  14. grid: boolean;
  15. // 网格大小
  16. gridSize: number;
  17. // 显示跨线
  18. jumpover: boolean;
  19. // 显示打印分割线
  20. printLine: boolean;
  21. // 显示水印
  22. watermark: boolean;
  23. // 水印文字
  24. watermarkText: string;
  25. }
  26. export default function appModel() {
  27. const [projectInfo, setProjectInfo] = useState({
  28. name: "新建流程图",
  29. desc: "",
  30. version: "",
  31. author: "",
  32. });
  33. // 隐藏/显示右侧面板
  34. const [showRightPanel, setShowRightPanel] = useState(true);
  35. // 格式刷启用
  36. const [enableFormatBrush, setEnableFormatBrush] = useState(false);
  37. // 格式刷样式
  38. const formatBrushStyle = useRef<cellStyle>();
  39. // 左侧面板激活
  40. const [leftPanelActiveKey, setLeftPanelActiveKey] = useState("1");
  41. // 右侧面板tab activeKey
  42. const [rightPanelTabActiveKey, setRightPanelTabActiveKey] = useState("1");
  43. const graphRef = useRef<Graph>();
  44. const [pageState, setPageState] = useState<PageSettings>({
  45. backgroundColor: "transparent",
  46. width: 0,
  47. height: 0,
  48. grid: true,
  49. gridSize: 15,
  50. jumpover: false,
  51. printLine: false,
  52. watermark: false,
  53. watermarkText: "沙鲁低码平台"
  54. });
  55. const [historyColor, setHistoryColor] = useState<string[]>([
  56. '#B0E38F',
  57. '#F19594',
  58. '#EC7270',
  59. '#996A99',
  60. '#4F374F',
  61. '#94E0E1',
  62. '#FBF1B8',
  63. '#E3F0E1',
  64. '#FDF8DC',
  65. '#569230',
  66. ]);
  67. // 收折右侧样式面板
  68. const toggleRightPanel = (show?: boolean) => {
  69. if(show !== undefined) setShowRightPanel(show);
  70. else setShowRightPanel(!showRightPanel);
  71. }
  72. // 处理页面设置
  73. const onChangePageSettings = (key: keyof PageSettings, value: any) => {
  74. setPageState((state) => {
  75. return {
  76. ...state,
  77. [key]: value
  78. }
  79. })
  80. }
  81. /**
  82. * 新增颜色记录
  83. * 添加时,将移除最早的颜色
  84. * @param color 颜色
  85. */
  86. const addHistoryCoolor = (color: string) => {
  87. if( historyColor.includes(color)) return;
  88. setHistoryColor((state) => {
  89. const newState = [...state];
  90. newState.unshift(color);
  91. newState.pop();
  92. return newState;
  93. })
  94. }
  95. useEffect(() => {
  96. const graphRoot = document.querySelector(
  97. "#graph-container"
  98. ) as HTMLDivElement;
  99. const pageRoot = document.querySelector(
  100. "#flow_canvas_container"
  101. ) as HTMLDivElement;
  102. if(enableFormatBrush) {
  103. graphRoot && (graphRoot.style.cursor = `url(${brushImg}), auto`);
  104. pageRoot && (pageRoot.style.cursor = `url(${brushImg}), auto`);
  105. } else {
  106. graphRoot && (graphRoot.style.cursor = "default");
  107. pageRoot && (pageRoot.style.cursor = "default");
  108. }
  109. }, [enableFormatBrush])
  110. const handleClick = (args: EventArgs & { cell: Cell }) => {
  111. // 取消格式刷
  112. if(!args?.cell || args?.cell?.data?.isPage) {
  113. formatBrushStyle.current = undefined;
  114. setEnableFormatBrush(false);
  115. graphRef.current?.off("cell:click", handleClick);
  116. graphRef.current?.off("blank:click", handleClick);
  117. } else {
  118. if(args.cell.data?.lock) return;
  119. // 应用格式刷
  120. const data = args.cell.data;
  121. args.cell.setData({
  122. text: formatBrushStyle.current?.text || data?.text,
  123. fill: formatBrushStyle.current?.fill || data?.fill,
  124. stroke: formatBrushStyle.current?.stroke || data?.stroke,
  125. opacity: formatBrushStyle.current?.opacity || data?.opacity
  126. })
  127. }
  128. };
  129. // 开启格式刷
  130. const toggleFormatBrush = (graph: Graph) => {
  131. graphRef.current = graph;
  132. const cell = graph?.getSelectedCells()?.find(item => item.isNode());
  133. setEnableFormatBrush((state) => {
  134. if(!state) {
  135. const data = cell?.getData();
  136. formatBrushStyle.current = data;
  137. message.info('格式刷已开启');
  138. graph.on("cell:click", handleClick);
  139. graph.on("blank:click", handleClick);
  140. } else {
  141. formatBrushStyle.current = undefined;
  142. graph.off("cell:click", handleClick);
  143. graph.off("blank:click", handleClick);
  144. }
  145. return !state;
  146. });
  147. }
  148. document.addEventListener("keydown", (e) => {
  149. if (e.key === "Escape") {
  150. setEnableFormatBrush(false);
  151. }
  152. });
  153. return {
  154. showRightPanel,
  155. toggleRightPanel,
  156. pageState,
  157. onChangePageSettings,
  158. historyColor,
  159. addHistoryCoolor,
  160. enableFormatBrush,
  161. toggleFormatBrush,
  162. projectInfo,
  163. setProjectInfo,
  164. rightPanelTabActiveKey,
  165. setRightPanelTabActiveKey,
  166. leftPanelActiveKey,
  167. setLeftPanelActiveKey,
  168. }
  169. }