|
@@ -1,10 +1,20 @@
|
|
|
-import { Graph, Node } from "@antv/x6"
|
|
|
+import { Graph, Node } from "@antv/x6";
|
|
|
import { Button, Form, Input, Modal, Radio } from "antd";
|
|
|
import { CheckCard } from "@ant-design/pro-components";
|
|
|
-import insertCss from 'insert-css';
|
|
|
+import insertCss from "insert-css";
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
+import { Export } from "@antv/x6-plugin-export";
|
|
|
+import { Scroller } from "@antv/x6-plugin-scroller";
|
|
|
|
|
|
-const ExportComponent = ({graph, getModal, type}: { graph: Graph, getModal?: () => { destroy: () => void}, type?: 'svg' | 'png' | 'jpg'},) => {
|
|
|
+const ExportComponent = ({
|
|
|
+ graph,
|
|
|
+ getModal,
|
|
|
+ type,
|
|
|
+}: {
|
|
|
+ graph: Graph;
|
|
|
+ getModal?: () => { destroy: () => void };
|
|
|
+ type?: "svg" | "png" | "jpg";
|
|
|
+}) => {
|
|
|
insertCss(`
|
|
|
.ant-pro-checkcard-content {
|
|
|
padding-block: 8px;
|
|
@@ -14,11 +24,17 @@ const ExportComponent = ({graph, getModal, type}: { graph: Graph, getModal?: ()
|
|
|
const graphRef = useRef<HTMLDivElement>(null);
|
|
|
const printGraph = useRef<Graph>();
|
|
|
const data = graph.toJSON();
|
|
|
- console.log('graph data', data);
|
|
|
+ data.cells = data.cells.filter((cell) => !cell?.data?.isPage);
|
|
|
+ data.cells.forEach((cell) => {
|
|
|
+ if(cell.data) {
|
|
|
+ cell.data.lock = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ console.log("graph data", data);
|
|
|
|
|
|
useEffect(() => {
|
|
|
- if(!graphRef.current) return;
|
|
|
-
|
|
|
+ if (!graphRef.current) return;
|
|
|
+
|
|
|
printGraph.current = new Graph({
|
|
|
container: graphRef.current,
|
|
|
autoResize: true,
|
|
@@ -42,95 +58,169 @@ const ExportComponent = ({graph, getModal, type}: { graph: Graph, getModal?: ()
|
|
|
stopDelegateOnDragging: true,
|
|
|
toolsAddable: false,
|
|
|
},
|
|
|
- });
|
|
|
+ })
|
|
|
+ .use(new Export())
|
|
|
+ .use(new Scroller({
|
|
|
+ enabled: true,
|
|
|
+ pannable: true,
|
|
|
+ autoResize: true,
|
|
|
+ }));
|
|
|
printGraph.current.fromJSON(data);
|
|
|
+ printGraph.current.centerContent();
|
|
|
}, []);
|
|
|
|
|
|
const [formModel, setFormModel] = useState({
|
|
|
- type: type || 'png',
|
|
|
+ type: type || "png",
|
|
|
quality: 1,
|
|
|
watermark: "严禁复制",
|
|
|
- watermarkStyle: 1
|
|
|
+ watermarkStyle: 1,
|
|
|
});
|
|
|
|
|
|
const handleExport = () => {
|
|
|
- switch(formModel.type) {
|
|
|
- case 'png':
|
|
|
- graph.exportPNG('', {
|
|
|
- quality: formModel.quality === 1 ? 1 : 0.6
|
|
|
+ switch (formModel.type) {
|
|
|
+ case "png":
|
|
|
+ printGraph.current?.exportPNG("", {
|
|
|
+ quality: formModel.quality === 1 ? 1 : 0.6,
|
|
|
+ // copyStyles: false,
|
|
|
});
|
|
|
break;
|
|
|
- case 'jpg':
|
|
|
- graph.exportJPEG('', {
|
|
|
- quality: formModel.quality === 1 ? 1 : 0.6
|
|
|
+ case "jpg":
|
|
|
+ printGraph.current?.exportJPEG("", {
|
|
|
+ quality: formModel.quality === 1 ? 1 : 0.6,
|
|
|
+ // copyStyles: false,
|
|
|
});
|
|
|
break;
|
|
|
- default:
|
|
|
- graph.exportSVG('', {
|
|
|
-
|
|
|
+ default:
|
|
|
+ printGraph.current?.exportSVG("", {
|
|
|
+ // copyStyles: false,
|
|
|
});
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
const handleSetFormValue = (key: string, value: any) => {
|
|
|
- setFormModel(state => ({...state, [key]: value}))
|
|
|
- }
|
|
|
+ setFormModel((state) => ({ ...state, [key]: value }));
|
|
|
+ };
|
|
|
|
|
|
const modal = getModal?.();
|
|
|
|
|
|
- return <div className="flex">
|
|
|
- <div className="h-500px flex-1 bg-#f3f5f9 rounded-4px">
|
|
|
- <div className="graph-container" ref={graphRef}></div>
|
|
|
- </div>
|
|
|
- <div className="flex-1 p-10px">
|
|
|
- <div className="flex flex-col">
|
|
|
- <div className="flex-1">
|
|
|
- <Form layout="vertical" size="small">
|
|
|
- <Form.Item label="图片格式">
|
|
|
- <CheckCard.Group className="flex" value={formModel.type} onChange={(value) => handleSetFormValue("type", value)}>
|
|
|
- <CheckCard className="w-100px h-40px" title="PNG" value={'png'}></CheckCard>
|
|
|
- <CheckCard className="w-100px h-40px" title="JPG" value={'jpg'}></CheckCard>
|
|
|
- <CheckCard className="w-100px h-40px" title="SVG" value={'svg'}></CheckCard>
|
|
|
- </CheckCard.Group>
|
|
|
- </Form.Item>
|
|
|
- {
|
|
|
- formModel.type !== 'svg' && <Form.Item label="图片质量">
|
|
|
- <Radio.Group value={formModel.quality} onChange={(e) => handleSetFormValue("quality", e.target.value)}>
|
|
|
- <Radio.Button value={1}>高清</Radio.Button>
|
|
|
- <Radio.Button value={2}>普通</Radio.Button>
|
|
|
- </Radio.Group>
|
|
|
- </Form.Item>
|
|
|
- }
|
|
|
- <Form.Item label="水印设置">
|
|
|
- <Input placeholder="请输入水印内容" value={formModel.watermark} onChange={(e) => handleSetFormValue("watermark", e.target.value)} />
|
|
|
- </Form.Item>
|
|
|
- <Form.Item label="水印样式">
|
|
|
- <CheckCard.Group className="flex flex-wrap" value={formModel.watermarkStyle} onChange={(value) => handleSetFormValue("watermarkStyle", value)} >
|
|
|
- <CheckCard className="w-96px h-50px" title="文字水印" value={1}></CheckCard>
|
|
|
- <CheckCard className="w-96px h-50px" title="图片水印" value={2}></CheckCard>
|
|
|
- <CheckCard className="w-96px h-50px" title="图片水印" value={3}></CheckCard>
|
|
|
- <CheckCard className="w-96px h-50px" title="图片水印" value={4}></CheckCard>
|
|
|
- <CheckCard className="w-96px h-50px" title="图片水印" value={5}></CheckCard>
|
|
|
- <CheckCard className="w-96px h-50px" title="图片水印" value={6}></CheckCard>
|
|
|
- </CheckCard.Group>
|
|
|
- </Form.Item>
|
|
|
- </Form>
|
|
|
+ return (
|
|
|
+ <div className="flex">
|
|
|
+ <div className="h-500px flex-1 bg-#f3f5f9 rounded-4px">
|
|
|
+ <div className="graph-container" ref={graphRef}></div>
|
|
|
</div>
|
|
|
- <div className="flex justify-end gap-8px">
|
|
|
- <Button size="small" onClick={() => modal?.destroy()}>取消</Button>
|
|
|
- <Button size="small" type="primary" onClick={handleExport}>开始导出</Button>
|
|
|
+ <div className="flex-1 p-10px">
|
|
|
+ <div className="flex flex-col">
|
|
|
+ <div className="flex-1">
|
|
|
+ <Form layout="vertical" size="small">
|
|
|
+ <Form.Item label="图片格式">
|
|
|
+ <CheckCard.Group
|
|
|
+ className="flex"
|
|
|
+ value={formModel.type}
|
|
|
+ onChange={(value) => handleSetFormValue("type", value)}
|
|
|
+ >
|
|
|
+ <CheckCard
|
|
|
+ className="w-100px h-40px"
|
|
|
+ title="PNG"
|
|
|
+ value={"png"}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-100px h-40px"
|
|
|
+ title="JPG"
|
|
|
+ value={"jpg"}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-100px h-40px"
|
|
|
+ title="SVG"
|
|
|
+ value={"svg"}
|
|
|
+ ></CheckCard>
|
|
|
+ </CheckCard.Group>
|
|
|
+ </Form.Item>
|
|
|
+ {formModel.type !== "svg" && (
|
|
|
+ <Form.Item label="图片质量">
|
|
|
+ <Radio.Group
|
|
|
+ value={formModel.quality}
|
|
|
+ onChange={(e) =>
|
|
|
+ handleSetFormValue("quality", e.target.value)
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <Radio.Button value={1}>高清</Radio.Button>
|
|
|
+ <Radio.Button value={2}>普通</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </Form.Item>
|
|
|
+ )}
|
|
|
+ <Form.Item label="水印设置">
|
|
|
+ <Input
|
|
|
+ placeholder="请输入水印内容"
|
|
|
+ value={formModel.watermark}
|
|
|
+ onChange={(e) =>
|
|
|
+ handleSetFormValue("watermark", e.target.value)
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label="水印样式">
|
|
|
+ <CheckCard.Group
|
|
|
+ className="flex flex-wrap"
|
|
|
+ value={formModel.watermarkStyle}
|
|
|
+ onChange={(value) =>
|
|
|
+ handleSetFormValue("watermarkStyle", value)
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <CheckCard
|
|
|
+ className="w-96px h-50px"
|
|
|
+ title="文字水印"
|
|
|
+ value={1}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-96px h-50px"
|
|
|
+ title="图片水印"
|
|
|
+ value={2}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-96px h-50px"
|
|
|
+ title="图片水印"
|
|
|
+ value={3}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-96px h-50px"
|
|
|
+ title="图片水印"
|
|
|
+ value={4}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-96px h-50px"
|
|
|
+ title="图片水印"
|
|
|
+ value={5}
|
|
|
+ ></CheckCard>
|
|
|
+ <CheckCard
|
|
|
+ className="w-96px h-50px"
|
|
|
+ title="图片水印"
|
|
|
+ value={6}
|
|
|
+ ></CheckCard>
|
|
|
+ </CheckCard.Group>
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </div>
|
|
|
+ <div className="flex justify-end gap-8px">
|
|
|
+ <Button size="small" onClick={() => modal?.destroy()}>
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ <Button size="small" type="primary" onClick={handleExport}>
|
|
|
+ 开始导出
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-</div>
|
|
|
-}
|
|
|
-export const exportImage = (graph: Graph, type?: 'svg' | 'png' | 'jpg') => {
|
|
|
+ );
|
|
|
+};
|
|
|
+export const exportImage = (graph: Graph, type?: "svg" | "png" | "jpg") => {
|
|
|
const modal = Modal.info({
|
|
|
title: "下载预览",
|
|
|
icon: <></>,
|
|
|
width: 800,
|
|
|
closable: true,
|
|
|
footer: <></>,
|
|
|
- content: <ExportComponent graph={graph} getModal={() => modal} type={type} />,
|
|
|
- })
|
|
|
-}
|
|
|
+ content: (
|
|
|
+ <ExportComponent graph={graph} getModal={() => modal} type={type} />
|
|
|
+ ),
|
|
|
+ });
|
|
|
+};
|