Aurora Admin v1.2.0: 79 components x 5 ends, doc site, contracts batch 1, playground, regression, deploy ready

This commit is contained in:
aurora-admin
2026-09-10 19:21:56 +08:00
commit 51ce3a28f7
654 changed files with 49082 additions and 0 deletions
+92
View File
@@ -0,0 +1,92 @@
import React, { useRef, useState, useEffect } from 'react';
import './SignaturePad.css';
export default function SignaturePad() {
const pad = useRef(null);
const canvas = useRef(null);
const drawing = useRef(false);
const last = useRef(null);
const strokes = useRef([]);
const cur = useRef([]);
const [hasInk, setHasInk] = useState(false);
const [saved, setSaved] = useState('');
const ctx = () => canvas.current.getContext('2d');
const fit = () => {
const r = pad.current.getBoundingClientRect();
canvas.current.width = r.width;
canvas.current.height = r.height;
redraw();
};
const pos = (e) => {
const r = canvas.current.getBoundingClientRect();
const t = e.touches && e.touches[0];
return { x: (t ? t.clientX : e.clientX) - r.left, y: (t ? t.clientY : e.clientY) - r.top };
};
const down = (e) => {
e.preventDefault();
drawing.current = true;
last.current = pos(e);
cur.current = [last.current];
strokes.current.push(cur.current);
setHasInk(true);
};
const move = (e) => {
if (!drawing.current) return;
e.preventDefault();
const p = pos(e);
ctx().lineTo(p.x, p.y);
ctx().stroke();
cur.current.push(p);
};
const up = () => { drawing.current = false; last.current = null; };
const undo = () => { strokes.current.pop(); redraw(); if (!strokes.current.length) setHasInk(false); };
const clear = () => { strokes.current = []; redraw(); setHasInk(false); setSaved(''); };
const save = () => setSaved('已导出(' + canvas.current.width + '×' + canvas.current.height + ')');
const redraw = () => {
const c = canvas.current;
const x = c.getContext('2d');
x.clearRect(0, 0, c.width, c.height);
x.strokeStyle = '#1F2329';
x.lineWidth = 2;
x.lineCap = 'round';
x.lineJoin = 'round';
strokes.current.forEach((s) => {
x.beginPath();
s.forEach((p, i) => (i ? x.lineTo(p.x, p.y) : x.moveTo(p.x, p.y)));
x.stroke();
});
};
useEffect(() => {
fit();
window.addEventListener('resize', fit);
return () => window.removeEventListener('resize', fit);
// eslint-disable-next-line
}, []);
return (
<div className="aa-sign">
<div className="aa-sign-pad" ref={pad}>
<canvas
ref={canvas}
className="aa-sign-canvas"
onMouseDown={down}
onMouseMove={move}
onMouseUp={up}
onTouchStart={down}
onTouchMove={move}
onTouchEnd={up}
/>
{!hasInk && <div className="aa-sign-placeholder">请在此处签名</div>}
</div>
<div className="aa-sign-actions">
<button className="aa-btn" onClick={undo}>撤销</button>
<button className="aa-btn" onClick={clear}>清除</button>
<button className="aa-btn aa-btn--primary" onClick={save}>保存</button>
{saved && <span className="aa-sign-preview">{saved}</span>}
</div>
</div>
);
}