|
@@ -1,63 +1,30 @@
|
|
|
import CustomColorPicker from "@/components/CustomColorPicker";
|
|
|
import {
|
|
|
BoldOutlined,
|
|
|
- ColumnHeightOutlined,
|
|
|
FontSizeOutlined,
|
|
|
ItalicOutlined,
|
|
|
- PictureOutlined,
|
|
|
StrikethroughOutlined,
|
|
|
- SwapOutlined,
|
|
|
UnderlineOutlined,
|
|
|
VerticalAlignBottomOutlined,
|
|
|
VerticalAlignMiddleOutlined,
|
|
|
VerticalAlignTopOutlined,
|
|
|
} from "@ant-design/icons";
|
|
|
-import {
|
|
|
- Button,
|
|
|
- Checkbox,
|
|
|
- Col,
|
|
|
- Divider,
|
|
|
- Form,
|
|
|
- Input,
|
|
|
- InputNumber,
|
|
|
- Row,
|
|
|
- Select,
|
|
|
- Tooltip,
|
|
|
-} from "antd";
|
|
|
-import { arrowOptions } from "@/pages/flow/data";
|
|
|
-import { useModel } from "umi";
|
|
|
+import { Button, Checkbox, Divider, InputNumber, Select, Tooltip } from "antd";
|
|
|
+import { Icon, useModel } from "umi";
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
-import { ImageFillType, ConnectorType, LineType } from "@/enum";
|
|
|
+import { ImageFillType, BorderSize, TopicType } from "@/enum";
|
|
|
import { set, cloneDeep } from "lodash-es";
|
|
|
import { Cell } from "@antv/x6";
|
|
|
-import { fontFamilyOptions, alignOptionData } from "@/pages/flow/data";
|
|
|
-import { alignCell, matchSize } from "@/utils";
|
|
|
-import { cellStyle } from "@/types";
|
|
|
-
|
|
|
-type FormModel = {
|
|
|
- opacity: number;
|
|
|
- width: number;
|
|
|
- height: number;
|
|
|
- x: number;
|
|
|
- y: number;
|
|
|
- rotation: number;
|
|
|
- connectorType: ConnectorType;
|
|
|
- startArrow: string;
|
|
|
- endArrow: string;
|
|
|
-} & cellStyle;
|
|
|
+import { fontFamilyOptions } from "@/pages/flow/data";
|
|
|
export default function GraphStyle() {
|
|
|
- const { selectedCell } = useModel("graphModel");
|
|
|
- const [isMulit, setIsMulit] = useState(false);
|
|
|
- const [hasEdge, setHasEdge] = useState(false);
|
|
|
+ const { selectedCell } = useModel("mindMapModel");
|
|
|
const eventNodeList = useRef<Cell[]>([]);
|
|
|
|
|
|
- const [formModel, setFormModel] = useState<FormModel>({
|
|
|
- opacity: 100,
|
|
|
- width: 20,
|
|
|
- height: 20,
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- rotation: 0,
|
|
|
+ const [formModel, setFormModel] = useState({
|
|
|
+ width: 100,
|
|
|
+ fixedWidth: false,
|
|
|
+ borderSize: BorderSize.medium,
|
|
|
+ type: TopicType.main,
|
|
|
text: {
|
|
|
fontFamily: "normal",
|
|
|
color: "#000000",
|
|
@@ -69,6 +36,7 @@ export default function GraphStyle() {
|
|
|
italic: false,
|
|
|
textDecoration: "none",
|
|
|
},
|
|
|
+ isFill: true,
|
|
|
fill: {
|
|
|
fillType: "color",
|
|
|
color1: "#FFFFFF",
|
|
@@ -78,37 +46,39 @@ export default function GraphStyle() {
|
|
|
objectFit: ImageFillType.Fill,
|
|
|
imageUrl: "",
|
|
|
},
|
|
|
+ isStroke: false,
|
|
|
stroke: {
|
|
|
type: "solid",
|
|
|
color: "#323232",
|
|
|
width: 1,
|
|
|
},
|
|
|
- connectorType: ConnectorType.Normal,
|
|
|
- startArrow: "",
|
|
|
- endArrow: "",
|
|
|
+ edge: {
|
|
|
+ color: "#000000",
|
|
|
+ width: 2,
|
|
|
+ },
|
|
|
});
|
|
|
|
|
|
useEffect(() => {
|
|
|
const firstNode = selectedCell?.find((item) => item.isNode());
|
|
|
- const firstEdge = selectedCell?.find((item) => item.isEdge());
|
|
|
eventNodeList.current = [];
|
|
|
if (firstNode) {
|
|
|
- const position = firstNode.position();
|
|
|
const size = firstNode.size();
|
|
|
const data = firstNode.getData();
|
|
|
setFormModel({
|
|
|
...formModel,
|
|
|
- x: position.x,
|
|
|
- y: position.y,
|
|
|
width: size.width,
|
|
|
- height: size.height,
|
|
|
- rotation: firstNode.angle(),
|
|
|
text: data.text,
|
|
|
fill: data.fill,
|
|
|
- stroke: data.stroke,
|
|
|
- connectorType: ConnectorType.Normal,
|
|
|
- startArrow: "",
|
|
|
- endArrow: "",
|
|
|
+ edge: data.edge,
|
|
|
+ fixedWidth: data.fixedWidth,
|
|
|
+ borderSize: data.borderSize,
|
|
|
+ type: data.type,
|
|
|
+ isFill: data.fill.color1 !== "transparent",
|
|
|
+ isStroke: data.stroke.width > 0,
|
|
|
+ stroke: {
|
|
|
+ ...data.stroke,
|
|
|
+ width: data.stroke.width || 1
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
// 监听当前选中节点的属性变化
|
|
@@ -137,135 +107,41 @@ export default function GraphStyle() {
|
|
|
setFormModel((state) => {
|
|
|
return {
|
|
|
...state,
|
|
|
+ type: args.current.type,
|
|
|
text: args.current.text,
|
|
|
fill: args.current.fill,
|
|
|
stroke: args.current.stroke,
|
|
|
+ edge: args.current.edge,
|
|
|
};
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- if (firstEdge) {
|
|
|
- const data = firstEdge.getData();
|
|
|
- const attrs = firstEdge.attrs || {};
|
|
|
- const sourceMarker = attrs.line?.sourceMarker as Record<string, any>;
|
|
|
- const targetMarker = attrs.line?.targetMarker as Record<string, any>;
|
|
|
- const lineType =
|
|
|
- attrs.line?.strokeDasharray === LineType.solid
|
|
|
- ? "solid"
|
|
|
- : attrs.line?.strokeDasharray === LineType.dashed
|
|
|
- ? "dashed"
|
|
|
- : attrs.line?.strokeDasharray === LineType.dotted
|
|
|
- ? "dotted"
|
|
|
- : "dashdot";
|
|
|
- let obj = {};
|
|
|
- if (!firstNode) {
|
|
|
- obj = {
|
|
|
- stroke: {
|
|
|
- type: lineType,
|
|
|
- color: attrs.line?.stroke || "#000000",
|
|
|
- width: attrs.line?.strokeWidth || 1,
|
|
|
- },
|
|
|
- };
|
|
|
- }
|
|
|
- setFormModel((state) => {
|
|
|
- return {
|
|
|
- ...state,
|
|
|
- ...obj,
|
|
|
- startArrow: sourceMarker?.name,
|
|
|
- endArrow: targetMarker?.name,
|
|
|
- };
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- let nodeCount = 0;
|
|
|
- selectedCell?.forEach((cell) => {
|
|
|
- if (cell.isEdge()) {
|
|
|
- // 存在边线
|
|
|
- setHasEdge(true);
|
|
|
- }
|
|
|
- if (cell.isNode()) nodeCount++;
|
|
|
- });
|
|
|
- // 多个节点
|
|
|
- setIsMulit(nodeCount > 1);
|
|
|
}, [selectedCell]);
|
|
|
|
|
|
// 表单值改变,修改元素属性
|
|
|
- const handleChange = (model: FormModel) => {
|
|
|
+ const handleChange = (model: typeof formModel) => {
|
|
|
selectedCell?.forEach((cell) => {
|
|
|
if (cell.isNode()) {
|
|
|
- cell.setPosition(model.x, model.y);
|
|
|
- cell.setSize(model.width, model.height);
|
|
|
- cell.rotate(model.rotation, { absolute: true });
|
|
|
+ model.fixedWidth && cell.setSize(model.width, cell.size().height);
|
|
|
cell.setData({
|
|
|
text: model.text,
|
|
|
- fill: model.fill,
|
|
|
- stroke: model.stroke,
|
|
|
- opacity: model.opacity,
|
|
|
- });
|
|
|
- }
|
|
|
- if (cell.isEdge()) {
|
|
|
- const attr = cell.attrs;
|
|
|
- const sourceMarker = attr?.line?.sourceMarker as Record<string, any>;
|
|
|
- const targetMarker = attr?.line?.targetMarker as Record<string, any>;
|
|
|
- cell.setAttrs({
|
|
|
- line: {
|
|
|
- ...(attr?.line || {}),
|
|
|
- stroke: model.stroke.color,
|
|
|
- strokeWidth: model.stroke.width,
|
|
|
- strokeDasharray: LineType[model.stroke.type],
|
|
|
- targetMarker: {
|
|
|
- ...(targetMarker || {}),
|
|
|
- name: model.endArrow,
|
|
|
- args: {
|
|
|
- size: model.stroke.width + 8,
|
|
|
- },
|
|
|
- },
|
|
|
- sourceMarker: {
|
|
|
- ...(sourceMarker || {}),
|
|
|
- name: model.startArrow,
|
|
|
- args: {
|
|
|
- size: model.stroke.width + 8,
|
|
|
- },
|
|
|
- },
|
|
|
+ edge: model.edge,
|
|
|
+ BorderSize: model.borderSize,
|
|
|
+ fill: {
|
|
|
+ ...model.fill,
|
|
|
+ color1: model.isFill ? model.fill.color1 : "transparent"
|
|
|
+ },
|
|
|
+ stroke: {
|
|
|
+ ...model.stroke,
|
|
|
+ width: model.isStroke ? model.stroke.width : 0
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- // 设置对齐方式
|
|
|
- const handleAlign = (
|
|
|
- type:
|
|
|
- | "left"
|
|
|
- | "hcenter"
|
|
|
- | "right"
|
|
|
- | "top"
|
|
|
- | "vcenter"
|
|
|
- | "bottom"
|
|
|
- | "h"
|
|
|
- | "v"
|
|
|
- ) => {
|
|
|
- selectedCell && alignCell(type, selectedCell);
|
|
|
- };
|
|
|
-
|
|
|
- // 匹配宽高
|
|
|
- const handleMatchSize = (type: "width" | "height" | "auto") => {
|
|
|
- selectedCell && matchSize(type, selectedCell);
|
|
|
- };
|
|
|
-
|
|
|
- // 调换渐变色颜色
|
|
|
- const handleSwapColor = () => {
|
|
|
- const { color1, color2 } = formModel.fill;
|
|
|
- handleSetFormModel("fill", {
|
|
|
- ...formModel.fill,
|
|
|
- color1: color2,
|
|
|
- color2: color1,
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
// 设置表单数据
|
|
|
const handleSetFormModel = (key: string, value: any) => {
|
|
|
const obj = cloneDeep(formModel);
|
|
@@ -284,53 +160,53 @@ export default function GraphStyle() {
|
|
|
<Button
|
|
|
type="text"
|
|
|
icon={
|
|
|
- <i className="iconfont icon-a-icon16lianxianleixinghuizhilianxian" />
|
|
|
+ <Icon
|
|
|
+ icon="local:round-rect"
|
|
|
+ className="text-14px"
|
|
|
+ width="20"
|
|
|
+ />
|
|
|
}
|
|
|
className={
|
|
|
- formModel.connectorType === ConnectorType.Rounded
|
|
|
- ? "active"
|
|
|
- : ""
|
|
|
+ formModel.borderSize === BorderSize.none ? "active" : ""
|
|
|
}
|
|
|
- disabled={!hasEdge}
|
|
|
+ disabled={!selectedCell.length}
|
|
|
onClick={() =>
|
|
|
- handleSetFormModel("connectorType", ConnectorType.Rounded)
|
|
|
+ handleSetFormModel("borderSize", BorderSize.none)
|
|
|
}
|
|
|
/>
|
|
|
<Button
|
|
|
type="text"
|
|
|
- icon={
|
|
|
- <i className="iconfont icon-a-icon16lianxianleixingbeisaierquxian" />
|
|
|
- }
|
|
|
+ icon={<Icon icon="local:round-small" width="20" />}
|
|
|
className={
|
|
|
- formModel.connectorType === ConnectorType.Smooth
|
|
|
- ? "active"
|
|
|
- : ""
|
|
|
+ formModel.borderSize === BorderSize.medium ? "active" : ""
|
|
|
}
|
|
|
- disabled={!hasEdge}
|
|
|
+ disabled={!selectedCell.length}
|
|
|
onClick={() =>
|
|
|
- handleSetFormModel("connectorType", ConnectorType.Smooth)
|
|
|
+ handleSetFormModel("borderSize", BorderSize.medium)
|
|
|
}
|
|
|
/>
|
|
|
<Button
|
|
|
type="text"
|
|
|
- icon={
|
|
|
- <i className="iconfont icon-a-icon16lianxianleixinghuizhizhixian" />
|
|
|
- }
|
|
|
+ icon={<Icon icon="local:round-big" width="20" />}
|
|
|
className={
|
|
|
- formModel.connectorType === ConnectorType.Normal
|
|
|
- ? "active"
|
|
|
- : ""
|
|
|
+ formModel.borderSize === BorderSize.large ? "active" : ""
|
|
|
}
|
|
|
- disabled={!hasEdge}
|
|
|
+ disabled={!selectedCell.length}
|
|
|
onClick={() =>
|
|
|
- handleSetFormModel("connectorType", ConnectorType.Normal)
|
|
|
+ handleSetFormModel("borderSize", BorderSize.large)
|
|
|
}
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className="flex items-center justify-between">
|
|
|
- <Checkbox>固定宽度</Checkbox>
|
|
|
+ <Checkbox
|
|
|
+ disabled={!selectedCell?.length}
|
|
|
+ checked={formModel.fixedWidth}
|
|
|
+ onChange={(e) => handleSetFormModel("fixedWidth", e.target.checked)}
|
|
|
+ >
|
|
|
+ 固定宽度
|
|
|
+ </Checkbox>
|
|
|
<InputNumber
|
|
|
className="w-96px"
|
|
|
suffix={<FontSizeOutlined />}
|
|
@@ -338,9 +214,9 @@ export default function GraphStyle() {
|
|
|
min={12}
|
|
|
max={10000}
|
|
|
formatter={(val) => `${val}px`}
|
|
|
- disabled={!selectedCell?.length}
|
|
|
- value={formModel.text.fontSize}
|
|
|
- onChange={(val) => handleSetFormModel("text.fontSize", val)}
|
|
|
+ disabled={!formModel.fixedWidth}
|
|
|
+ value={formModel.width}
|
|
|
+ onChange={(val) => handleSetFormModel("width", val)}
|
|
|
/>
|
|
|
</div>
|
|
|
</section>
|
|
@@ -507,11 +383,17 @@ export default function GraphStyle() {
|
|
|
<Divider className="my-8px" />
|
|
|
<section className="px-16px">
|
|
|
<div className="flex items-center justify-between mb-8px">
|
|
|
- <Checkbox>边框</Checkbox>
|
|
|
- <CustomColorPicker
|
|
|
+ <Checkbox
|
|
|
disabled={!selectedCell?.length}
|
|
|
- color={formModel.fill.color1}
|
|
|
- onChange={(color) => handleSetFormModel("fill.color1", color)}
|
|
|
+ checked={formModel.isStroke}
|
|
|
+ onChange={(e) => handleSetFormModel("isStroke", e.target.checked)}
|
|
|
+ >
|
|
|
+ 边框
|
|
|
+ </Checkbox>
|
|
|
+ <CustomColorPicker
|
|
|
+ disabled={!formModel.isStroke}
|
|
|
+ color={formModel.stroke.color}
|
|
|
+ onChange={(color) => handleSetFormModel("stroke.color", color)}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="flex gap-12px mb-8px">
|
|
@@ -521,7 +403,7 @@ export default function GraphStyle() {
|
|
|
min={1}
|
|
|
max={10}
|
|
|
formatter={(val) => `${val}px`}
|
|
|
- disabled={!selectedCell?.length}
|
|
|
+ disabled={!formModel.isStroke}
|
|
|
value={formModel.stroke.width}
|
|
|
onChange={(val) => handleSetFormModel("stroke.width", val)}
|
|
|
/>
|
|
@@ -533,7 +415,7 @@ export default function GraphStyle() {
|
|
|
{ label: "点线", value: "dotted" },
|
|
|
{ label: "点划线", value: "dashdot" },
|
|
|
]}
|
|
|
- disabled={!selectedCell?.length}
|
|
|
+ disabled={!formModel.isStroke}
|
|
|
value={formModel.stroke.type}
|
|
|
onChange={(value) => handleSetFormModel("stroke.type", value)}
|
|
|
/>
|
|
@@ -542,9 +424,15 @@ export default function GraphStyle() {
|
|
|
<Divider className="my-8px" />
|
|
|
<section className="px-16px">
|
|
|
<div className="flex items-center justify-between mb-8px">
|
|
|
- <Checkbox>填充</Checkbox>
|
|
|
- <CustomColorPicker
|
|
|
+ <Checkbox
|
|
|
disabled={!selectedCell?.length}
|
|
|
+ checked={formModel.isFill}
|
|
|
+ onChange={(e) => handleSetFormModel("isFill", e.target.checked)}
|
|
|
+ >
|
|
|
+ 填充
|
|
|
+ </Checkbox>
|
|
|
+ <CustomColorPicker
|
|
|
+ disabled={!formModel.isFill}
|
|
|
color={formModel.fill.color1}
|
|
|
onChange={(color) => handleSetFormModel("fill.color1", color)}
|
|
|
/>
|
|
@@ -553,11 +441,11 @@ export default function GraphStyle() {
|
|
|
<Divider className="my-8px" />
|
|
|
<section className="px-16px">
|
|
|
<div className="flex items-center justify-between mb-8px">
|
|
|
- <Checkbox>连线</Checkbox>
|
|
|
+ <div className="font-bold mb-8px">连线</div>
|
|
|
<CustomColorPicker
|
|
|
- disabled={!selectedCell?.length}
|
|
|
- color={formModel.fill.color1}
|
|
|
- onChange={(color) => handleSetFormModel("fill.color1", color)}
|
|
|
+ disabled={!selectedCell?.length || formModel.type === TopicType.main}
|
|
|
+ color={formModel.edge.color}
|
|
|
+ onChange={(color) => handleSetFormModel("edge.color", color)}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="flex gap-12px mb-8px">
|
|
@@ -567,11 +455,11 @@ export default function GraphStyle() {
|
|
|
min={1}
|
|
|
max={10}
|
|
|
formatter={(val) => `${val}px`}
|
|
|
- disabled={!selectedCell?.length}
|
|
|
- value={formModel.stroke.width}
|
|
|
- onChange={(val) => handleSetFormModel("stroke.width", val)}
|
|
|
+ disabled={!selectedCell?.length || formModel.type === TopicType.main}
|
|
|
+ value={formModel.edge.width}
|
|
|
+ onChange={(val) => handleSetFormModel("edge.width", val)}
|
|
|
/>
|
|
|
- </div>
|
|
|
+ </div>
|
|
|
</section>
|
|
|
</div>
|
|
|
);
|