Skip to content

Commit

Permalink
Merge pull request #50 from guanweiwang/main
Browse files Browse the repository at this point in the history
feat: add immediate consultation
  • Loading branch information
zclaiqcc authored Apr 27, 2023
2 parents 44310f6 + 6b187e0 commit b25a575
Show file tree
Hide file tree
Showing 14 changed files with 612 additions and 14 deletions.
1 change: 1 addition & 0 deletions homepage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@emotion/styled": "^11.10.6",
"@jsdevtools/rehype-toc": "^3.0.2",
"@mui/icons-material": "^5.11.16",
"@mui/lab": "5.0.0-alpha.128",
"@mui/material": "^5.12.0",
"@types/node": "18.15.11",
"@types/react": "18.0.35",
Expand Down
67 changes: 67 additions & 0 deletions homepage/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

103 changes: 103 additions & 0 deletions homepage/src/components/Home/Version/Consultation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { useState, useEffect } from "react";
import { Message, Modal } from "@/components";
import { Box, TextField, Typography, Button } from "@mui/material";

function Consultation() {
const [text, setText] = useState("");
const [wrongPhoneNumber, setWrongPhoneNumber] = useState(false);
const [consultOpen, setConsultOpen] = useState(false);

const consultHandler = () => {
const valid = /^1[3-9]\d{9}$/.test(text);
setWrongPhoneNumber(!valid);
if (!valid) {
Message.error("手机号格式不正确");
return;
}
fetch("https://leads.chaitin.net/api/trial", {
// fetch('http://116.62.230.26:8999/api/trial', { // 测试用地址
method: "POST",
mode: "cors",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
phone: text,
platform_source: "product-official-site",
product_source: "safeline-ce",
source_detail: "来自雷池社区版官网",
}),
})
.then((d) => d.json())
.then((d) => {
if (d.code == 0) {
Message.success("提交成功");
} else {
Message.error("提交失败");
}
setConsultOpen(false);
});
};

const textHandler = (v: string) => {
setText(v);
};

useEffect(() => {
if (!consultOpen) {
setText("");
}
}, [consultOpen]);

return (
<>
<Button
variant="outlined"
sx={{
width: 200,
my: 2,
"&:hover": {
borderColor: "primary.main",
backgroundColor: "primary.main",
color: "#fff",
},
}}
onClick={() => setConsultOpen(true)}
>
立即咨询
</Button>
<Modal
open={consultOpen}
onCancel={() => setConsultOpen(false)}
title="咨询企业版"
okText="提交"
onOk={consultHandler}
sx={{ width: 600 }}
>
<Box sx={{}}>
<div style={{ margin: "10px 0 15px" }}>
<TextField
error={wrongPhoneNumber}
fullWidth
size="small"
label="手机号"
helperText={
wrongPhoneNumber ? "手机号格式不正确" : "请输入您的手机号"
}
variant="outlined"
value={text}
onChange={(e) => textHandler(e.target.value)}
/>
</div>
<Typography>
我们将在工作时间 2 小时内联系您,您的手机号不会用于其他目的
</Typography>
{/* <Typography id='modal-modal-description' sx={{ mt: 2 }}>
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography> */}
咨询企业版
</Box>
</Modal>
</>
);
}

export default Consultation;
16 changes: 2 additions & 14 deletions homepage/src/components/Home/Version/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Typography, Box, Button, alpha } from "@mui/material";
import Title from "@/components/Home/Title";
import FunctionTable from "./FunctionTable";
import Consultation from "./Consultation";
import Link from "next/link";
const FREE_FUNCTION = [
"智能语义分析检测",
Expand Down Expand Up @@ -116,20 +117,7 @@ const Version = () => {
<Typography variant="h5" sx={{ fontWeight: 500, fontSize: "18px" }}>
商业版
</Typography>
<Button
variant="outlined"
sx={{
width: 200,
my: 2,
"&:hover": {
borderColor: "primary.main",
backgroundColor: "primary.main",
color: "#fff",
},
}}
>
立即咨询
</Button>
<Consultation />
<Box>
{ENTERPRISE_FUNCTION.map((f) => (
<Box
Expand Down
57 changes: 57 additions & 0 deletions homepage/src/components/Message/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { type FC, useRef, useEffect } from 'react'

import { Alert as MAlert, type AlertColor } from '@mui/material'

interface AlertProps {
duration?: number
onClose?(key: React.Key): void
noticeKey: React.Key
content?: React.ReactNode
severity: AlertColor
}

const Alert: FC<AlertProps> = (props) => {
const { duration, severity, content, noticeKey, onClose } = props
const closeTimer = useRef<number | null>(null)

const startCloseTimer = () => {
if (duration) {
closeTimer.current = window.setTimeout(() => {
close()
}, duration * 1000)
}
}

const clearCloseTimer = () => {
if (closeTimer.current) {
clearTimeout(closeTimer.current)
closeTimer.current = null
}
}

const close = (e?: React.MouseEvent<HTMLAnchorElement>) => {
if (e) {
e.stopPropagation()
}
clearCloseTimer()
if (onClose) {
onClose(noticeKey)
}
}

useEffect(() => {
startCloseTimer()
return () => {
clearCloseTimer()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

return (
<MAlert severity={severity} sx={{ mb: '10px' }}>
{content}
</MAlert>
)
}

export default Alert
100 changes: 100 additions & 0 deletions homepage/src/components/Message/Message.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useState, forwardRef, useImperativeHandle } from "react";

import { Snackbar, Box, type AlertColor } from "@mui/material";

import { ThemeProvider } from "@/components";
import { render, unmount } from "@/utils";

import Alert from "./Alert";

export interface Notice {
key?: React.Key;
content?: React.ReactNode;
severity: AlertColor;
onClose?: () => void;
}

interface MessageProps {}

let seed = 0;
const now = Date.now();

function getUuid() {
const id = seed;
seed += 1;
return `ctMessage_${now}_${id}`;
}

// eslint-disable-next-line react/display-name
const Message = forwardRef<any, MessageProps>((props, ref) => {
const [notices, setNotices] = useState<Notice[]>([]);
const add = (notice: Notice) => {
const key = notice.key ?? getUuid();
setNotices((state) => {
state.push({ ...notice, key });
return [...state];
});
};

const remove = (key: React.Key) => {
setNotices((state) => state.filter((s) => s.key !== key));
};

useImperativeHandle(ref, () => ({
add,
remove,
}));

return (
<ThemeProvider>
<Snackbar open anchorOrigin={{ vertical: "top", horizontal: "center" }}>
<Box>
{notices.map((item) => {
const alertProps = {
...item,
noticeKey: item.key!,
onClose: (noticeKey: React.Key) => {
remove(noticeKey);
},
};
return <Alert {...alertProps} key={item.key} />;
})}
</Box>
</Snackbar>
</ThemeProvider>
);
});

// @ts-ignore
Message.newInstance = (properties: MessageProps, callback) => {
const { ...props } = properties || {};
const div = document?.createElement("div");
document.body.appendChild(div);
let called = false;
function ref(notification: any) {
if (called) {
return;
}
called = true;
callback({
notice(noticeProps: MessageProps) {
notification.add(noticeProps);
},
removeNotice(key: React.Key) {
notification.remove(key);
},
component: notification,
destroy() {
unmount(div);
if (div.parentNode) {
div.parentNode.removeChild(div);
}
},
});
}
setTimeout(() => {
render(<Message {...props} ref={ref} />, div);
});
};

export default Message;
Loading

0 comments on commit b25a575

Please sign in to comment.