新增Signature签字组件
parent
7485d77973
commit
a4e026b838
|
|
@ -59,12 +59,12 @@ const FormBuilder = (props) => {
|
||||||
{submitButtonText}
|
{submitButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{extraActionButtons}
|
||||||
{showCancelButton && (
|
{showCancelButton && (
|
||||||
<Button onClick={handleCancel}>
|
<Button onClick={handleCancel}>
|
||||||
{cancelButtonText}
|
{cancelButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{extraActionButtons}
|
|
||||||
</Space>
|
</Space>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import type { FC } from "react";
|
||||||
|
|
||||||
|
export interface SignatureValue {
|
||||||
|
/** 签字时间,YYYY-MM-DD HH:mm:ss */
|
||||||
|
time: string;
|
||||||
|
/** 签字图片的base64编码 */
|
||||||
|
base64: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SignatureProps {
|
||||||
|
/** 确认签字回调 */
|
||||||
|
onConfirm: (value: SignatureValue) => void;
|
||||||
|
/** 签字区域宽度,默认为 752 */
|
||||||
|
width?: number;
|
||||||
|
/** 签字区域高度,默认为 300 */
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签字组件
|
||||||
|
*/
|
||||||
|
declare const Signature: FC<SignatureProps>;
|
||||||
|
|
||||||
|
export default Signature;
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
import { Button, Image, message, Modal } from "antd";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
|
import { base642File } from "../../utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签字组件
|
||||||
|
*/
|
||||||
|
function Signature(props) {
|
||||||
|
const {
|
||||||
|
onConfirm,
|
||||||
|
width = 752,
|
||||||
|
height = 300,
|
||||||
|
...restProps
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const [signatureModalOpen, setSignatureModalOpen] = useState(false);
|
||||||
|
const signatureCanvas = useRef(null);
|
||||||
|
const [base64, setBase64] = useState("");
|
||||||
|
|
||||||
|
const onOk = () => {
|
||||||
|
if (signatureCanvas.current.isEmpty()) {
|
||||||
|
message.warning("请签名");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const base64 = signatureCanvas.current.toDataURL();
|
||||||
|
setBase64(base64);
|
||||||
|
onConfirm({
|
||||||
|
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
base64,
|
||||||
|
file: base642File(base64),
|
||||||
|
});
|
||||||
|
signatureCanvas.current.clear();
|
||||||
|
setSignatureModalOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setSignatureModalOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{base64 ? "重新签字" : "手写签字"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{base64 && (
|
||||||
|
<div style={{ border: "1px dashed #d9d9d9", width, height, marginTop: 16 }}>
|
||||||
|
<Image src={base64} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<Modal
|
||||||
|
title="签字"
|
||||||
|
width={800}
|
||||||
|
open={signatureModalOpen}
|
||||||
|
onCancel={() => setSignatureModalOpen(false)}
|
||||||
|
footer={[
|
||||||
|
<Button key="clear" onClick={() => signatureCanvas.current.clear()}>重签</Button>,
|
||||||
|
<Button
|
||||||
|
key="cancel"
|
||||||
|
onClick={() => {
|
||||||
|
setSignatureModalOpen(false);
|
||||||
|
signatureCanvas.current.clear();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</Button>,
|
||||||
|
<Button key="ok" type="primary" onClick={onOk}>确定</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<div style={{ border: "1px dashed #d9d9d9" }}>
|
||||||
|
<SignatureCanvas
|
||||||
|
ref={signatureCanvas}
|
||||||
|
penColor="black"
|
||||||
|
canvasProps={{ width, height }}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Signature;
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.18",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-pdf": "^10.2.0"
|
"react-pdf": "^10.2.0",
|
||||||
|
"react-signature-canvas": "^1.1.0-alpha.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,11 @@ export function getIndexColumn(pagination: false | BasePaginationConfig): {
|
||||||
*/
|
*/
|
||||||
export function getFileUrl(): string;
|
export function getFileUrl(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base64转File对象
|
||||||
|
*/
|
||||||
|
export function base642File(base64: string, filename?: string): File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取树形节点路径
|
* 获取树形节点路径
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,23 @@ export function image2Base642(file) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
base64转File对象
|
||||||
|
*/
|
||||||
|
export function base642File(base64, filename = "file") {
|
||||||
|
const arr = base64.split(",");
|
||||||
|
const mime = arr[0].match(/:(.*?);/)[1];
|
||||||
|
const bstr = atob(arr[1]);
|
||||||
|
let n = bstr.length;
|
||||||
|
const u8arr = new Uint8Array(n);
|
||||||
|
|
||||||
|
while (n--) {
|
||||||
|
u8arr[n] = bstr.charCodeAt(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new File([u8arr], filename, { type: mime });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断图片是否可访问成功
|
* 判断图片是否可访问成功
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue