125 lines
3.3 KiB
JavaScript
125 lines
3.3 KiB
JavaScript
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||
|
import { Spin } from "antd";
|
||
|
import { LoadingOutlined } from "@ant-design/icons";
|
||
|
import { useRule } from "./PackagingOperation/hooks"
|
||
|
|
||
|
const btnTyps = [
|
||
|
{ type: "primary", color: "#0185FF" },
|
||
|
{ type: "danger", color: "#F5222D" },
|
||
|
{ type: "warning", color: "#FAAB0C" },
|
||
|
{ type: "success", color: "#85C700" },
|
||
|
{ type: "info", color: "#26c1e1" },
|
||
|
{ type: "default", color: "rgba(0,0,0,.85)" },
|
||
|
];
|
||
|
export const Button = React.memo((props) => {
|
||
|
const {
|
||
|
visible = true,
|
||
|
enable = true,
|
||
|
title,
|
||
|
type = "primary",
|
||
|
ghost = false,
|
||
|
size,
|
||
|
onClick = () => { },
|
||
|
ruleCode,
|
||
|
} = props;
|
||
|
|
||
|
const rule = useRule(ruleCode);
|
||
|
// useEffect(() => {
|
||
|
// console.log("rule", rule)
|
||
|
// }, [rule])
|
||
|
|
||
|
const types = useRef(btnTyps.map(({ type }) => type));
|
||
|
|
||
|
const sizes = useRef(["large"]);
|
||
|
const className = useMemo(() => {
|
||
|
let res = "client-btn";
|
||
|
if (type && types.current.includes(type)) res += ` btn-${type}`;
|
||
|
if (ghost === true) res += ` btn-ghost`;
|
||
|
if (size && sizes.current.includes(size)) res += ` btn-${size}`;
|
||
|
if (enable === false) res += ` btn-disabled`;
|
||
|
return res;
|
||
|
}, [type, ghost, size, enable]);
|
||
|
|
||
|
const [loading, setLoading] = useState(false);
|
||
|
const handleClick = useCallback(() => {
|
||
|
if (enable && !loading) {
|
||
|
let res = onClick();
|
||
|
if (res && typeof res.then == "function" && typeof res.finally == "function") {
|
||
|
setLoading(true);
|
||
|
res.finally(() => setLoading(false))
|
||
|
}
|
||
|
}
|
||
|
}, [enable, onClick, loading]);
|
||
|
|
||
|
if (!rule) return null;
|
||
|
if (!visible) return null;
|
||
|
return (
|
||
|
<div className={className} onClick={() => enable && handleClick()}>
|
||
|
{title}
|
||
|
<Spin
|
||
|
spinning={loading}
|
||
|
indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}
|
||
|
/>
|
||
|
<style jsx>{`
|
||
|
.client-btn {
|
||
|
border-radius: 2px;
|
||
|
cursor: pointer;
|
||
|
display: inline-block;
|
||
|
color: white;
|
||
|
line-height: 44px;
|
||
|
padding: 0 24px;
|
||
|
font-size: 20px;
|
||
|
user-select: none;
|
||
|
position: relative;
|
||
|
}
|
||
|
.client-btn.btn-large {
|
||
|
line-height: 56px;
|
||
|
font-size: 24px;
|
||
|
padding: 0 36px;
|
||
|
}
|
||
|
.client-btn.btn-disabled {
|
||
|
opacity: 0.4;
|
||
|
cursor: not-allowed;
|
||
|
}
|
||
|
${btnTyps
|
||
|
.map((item) => {
|
||
|
let { type, color } = item;
|
||
|
return `
|
||
|
.client-btn.btn-${type} {
|
||
|
background: ${color};
|
||
|
}
|
||
|
.client-btn.btn-ghost.btn-${type} {
|
||
|
background: transparent;
|
||
|
border: 1px solid;
|
||
|
color: ${color};
|
||
|
border-color: ${color};
|
||
|
}
|
||
|
`;
|
||
|
})
|
||
|
.join("") + "\n"}
|
||
|
.client-btn.btn-ghost {
|
||
|
}
|
||
|
.client-btn.btn-ghost.btn-default {
|
||
|
border-color: #d9d9d9;
|
||
|
}
|
||
|
`}</style>
|
||
|
<style jsx global>{`
|
||
|
.client-btn ~ .client-btn {
|
||
|
margin-left: 16px;
|
||
|
}
|
||
|
.client-btn .ant-spin {
|
||
|
width: 100%;
|
||
|
position: absolute;
|
||
|
height: 100%;
|
||
|
background: #ffffff87;
|
||
|
left: 0;
|
||
|
top: 0;
|
||
|
line-height: inherit;
|
||
|
}
|
||
|
.client-btn .ant-spin-dot {
|
||
|
}
|
||
|
`}</style>
|
||
|
</div>
|
||
|
);
|
||
|
});
|