style: 样式调整

This commit is contained in:
song_xiao_lin
2024-04-16 16:24:48 +08:00
parent e61f8bf041
commit 4cba932506
13 changed files with 822 additions and 14137 deletions
+61
View File
@@ -0,0 +1,61 @@
.Contro {
display: flex;
align-items: center;
height: 40px;
padding: 8px 16px;
font-size: 12px;
}
.Contro-error-bg {
background-color: rgba(244, 115, 107, .10);
}
.Contro-success-bg {
background-color: rgba(86, 201, 145, .10);
}
.Contro-cont-input {
height: 24px;
margin-right: 8px;
}
.Contro-lable {
color: #85899E;
}
.Contro-cont {
display: flex;
justify-content: space-between;
align-items: center;
flex: 1;
}
.Contro-cont-text-error {
color: #F6544A;
}
.Contro-cont-text-success {
color: #56C991;
}
.Contro-handle-icon {
display: flex;
align-items: center;
}
.Contro-handle-icon svg {
cursor: pointer;
}
.contro-handle-icon-check {
margin-left: 8px;
}
.icon-p {
display: inline-block;
padding: 4px;
}
.Contro-cont span.anticon:hover {
background: #F0F1F3;
}
+114
View File
@@ -0,0 +1,114 @@
import React, { useEffect, useState } from "react";
import { Divider, Tooltip, Input } from "antd";
import classNames from "classnames";
import {
CheckIcon,
ExitIcon,
PencilAltIcon,
RefreshIcon,
XIcon,
} from "@assets/icon/icon";
import "./Contro.css";
interface ControProps {}
export const Contro: React.FC<ControProps> = () => {
const [isEdit, setIsEdit] = useState<boolean>(false);
const [connected, setConnected] = useState(false);
const [autoFindFailedReason, setAutoFindFailedReason] = useState<string>("");
const [enginePort, setEnginePort] = useState<string>("0");
const [enginePortTemp, setEnginePortTemp] = useState<string>(enginePort);
// useEffect(() => {
// const updateStatus = () => {
// wsc.updateWSCStatus();
// };
// updateStatus();
// const id = setInterval(updateStatus, 500);
// wsc.onWSCMessage((req: { connected: boolean }) => {
// if (req["connected"] === undefined) {
// return;
// }
// console.log("connected", req.connected);
// setConnected(req.connected);
// });
// return () => {
// clearInterval(id);
// };
// }, []);
return (
<div
className={classNames("Contro", {
["Contro-success-bg"]: !autoFindFailedReason,
["Contro-error-bg"]: autoFindFailedReason,
})}
>
<div className="Contro-lable">Yakit 引擎连接状态:</div>
<div className="Contro-cont">
{isEdit ? (
<>
<Input
rootClassName="Contro-cont-input"
value={enginePortTemp}
onChange={(e) => {
// TODO 需要校验
const value = e.target.value;
setEnginePortTemp(value);
}}
/>
<div className="Contro-handle-icon">
<XIcon
className="icon-p"
onClick={() => {
setIsEdit(false);
}}
/>
<CheckIcon
className="contro-handle-icon-check icon-p"
onClick={() => {
setIsEdit(false);
setEnginePort(enginePortTemp);
}}
/>
</div>
</>
) : (
<>
<div
className={classNames("Contro-cont-text", {
["Contro-cont-text-success"]: !autoFindFailedReason,
["Contro-cont-text-error"]: autoFindFailedReason,
})}
>
{autoFindFailedReason
? autoFindFailedReason + "(" + enginePort + ")"
: "已连接(" + enginePort + ")"}
</div>
<div className="Contro-handle-icon">
<Tooltip title="修改监听端口">
<PencilAltIcon
className="icon-p"
onClick={() => {
setIsEdit(true);
setEnginePortTemp(enginePort);
}}
/>
</Tooltip>
<Divider type="vertical" style={{ height: 16 }} />
{autoFindFailedReason ? (
<Tooltip title="重新连接">
<RefreshIcon />
</Tooltip>
) : (
<Tooltip title="断开连接">
<ExitIcon />
</Tooltip>
)}
</div>
</>
)}
</div>
</div>
);
};
+113
View File
@@ -0,0 +1,113 @@
.Prox-title-wrap {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px 8px;
}
.Prox-title-wrap-left {
display: flex;
align-items: center;
}
.Prox-title-wrap-left .prox-title {
margin-right: 4px;
color: #31343F;
font-size: 14px;
font-weight: 600;
}
.Prox-title-wrap-left .prox-number {
display: inline-block;
width: 18px;
height: 16px;
text-align: center;
color: #85899E;
border-radius: 8px;
background: #F0F1F3;
font-size: 10px;
}
.Prox-title-wrap-right {
display: flex;
align-items: center;
cursor: pointer;
}
.Prox-title-wrap-right .Prox-add-text {
margin-right: 4px;
color: var(--yakit-primary);
font-size: 12px;
font-weight: 500;
}
.Prox-title-wrap-right .Prox-add-icon svg {
color: var(--yakit-primary);
}
.Prox-list-wrap {
overflow-y: auto;
max-height: 305px;
padding: 16px;
padding-top: 0;
}
.add-list {
display: flex;
justify-content: center;
align-items: center;
height: 28px;
cursor: pointer;
border: 1px solid #EAECF3;
border-radius: 4px;
background-color: #FFFFFF;
}
.add-list:hover {
border: 1px solid var(--yakit-primary);
}
.add-list .add-list-icon svg {
color: #85899E;
}
.Prox-list-wrap .add-list .add-list-text {
margin-left: 4px;
color: #31343F;
font-size: 14px;
font-weight: 600;
}
.Prox-list-wrap .Prox-list-item-wrap {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 8px;
border-radius: 8px;
}
.Prox-list-wrap .Prox-list-item-wrap:hover {
background-color: #F8F8F8;
}
.Prox-list-item-space .ant-space-item .ant-space-compact {
height: 28px;
}
.Prox-list-item-space .ant-space-item .ant-space-compact .ant-select-single {
height: 28px;
}
.Prox-list-wrap .Prox-list-item-wrap:hover .proxy-list-del-icon {
display: block;
}
.proxy-list-del-icon {
display: none;
cursor: pointer;
padding: 4px;
}
.proxy-list-del-icon:hover {
background: #F0F1F3;
}
+216
View File
@@ -0,0 +1,216 @@
import React, { useEffect, useState } from "react";
import { Space, Select, Input, Switch } from "antd";
import { PlusSmIcon, TrashIcon } from "@assets/icon/icon";
import { wsc } from "@network/chrome";
import "./Prox.css";
interface ProxyConfig {
id: string;
scheme: "http" | "socks5";
host: string;
port: string;
hostStatus: "error" | "";
portStatus: "error" | "";
open: boolean;
}
export interface ProxProps {}
export const Prox: React.FC<ProxProps> = () => {
const [proxyList, setProxyList] = useState<ProxyConfig[]>([]);
// proxy
useEffect(() => {
const update = () => {
wsc.updateProxyStatus();
};
update();
const id = setInterval(update, 500);
return () => {
clearInterval(id);
};
}, []);
useEffect(() => {
wsc.onProxyStatusMessage((msg) => {
if (msg["proxy"] === undefined || msg["enable"] === undefined) {
return;
}
console.log("当前代理:", msg);
});
}, []);
const hostOnchange = (value: string, id: string) => {
const ipPattern = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
const domainPattern = /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
const copyProxyList = structuredClone(proxyList);
if (value === "" || ipPattern.test(value) || domainPattern.test(value)) {
copyProxyList.forEach((i) => {
if (i.id === id) {
i.hostStatus = "";
i.host = value;
}
});
} else {
copyProxyList.forEach((i) => {
if (i.id === id) {
i.hostStatus = "error";
i.host = value;
}
});
}
setProxyList(copyProxyList);
};
const portOnchange = (value: string, id: string) => {
const portNumber = parseInt(value, 10);
const copyProxyList = structuredClone(proxyList);
if (
value === "" ||
(/^\d+$/.test(value) && portNumber >= 0 && portNumber <= 65535)
) {
copyProxyList.forEach((i) => {
if (i.id === id) {
i.portStatus = "";
i.port = value === "" ? "" : portNumber + "";
}
});
} else {
copyProxyList.forEach((i) => {
if (i.id === id) {
i.portStatus = "error";
i.port = value;
}
});
}
setProxyList(copyProxyList);
};
return (
<div className="Prox">
<div className="Prox-title-wrap">
<div className="Prox-title-wrap-left">
<span className="prox-title">设置代理</span>
<span className="prox-number">{proxyList.length}</span>
</div>
<div
className="Prox-title-wrap-right"
onClick={() => {
setProxyList([
...proxyList,
{
id: Math.random() + "",
scheme: "http",
host: "",
port: "",
hostStatus: "",
portStatus: "",
open: false,
},
]);
}}
>
<span className="Prox-add-text">添加</span>
<PlusSmIcon className="Prox-add-icon" />
</div>
</div>
<div className="Prox-list-wrap">
{proxyList.length ? (
proxyList.map((item) => (
<div className="Prox-list-item-wrap" key={item.id}>
<Space className="Prox-list-item-space">
<Space.Compact>
<Select
value={item.scheme}
style={{ width: 88 }}
disabled={item.open}
onChange={(value, option) => {
const copyProxyList = structuredClone(proxyList);
copyProxyList.forEach((i) => {
if (i.id === item.id) {
i.scheme = value;
}
});
setProxyList(copyProxyList);
}}
>
<Select.Option value="http">HTTP</Select.Option>
<Select.Option value="socks5">Socks5</Select.Option>
</Select>
<Input
value={item.host}
style={{ width: 136 }}
disabled={item.open}
status={item.hostStatus}
onChange={(e) => hostOnchange(e.target.value, item.id)}
/>
<Input
value={item.port}
style={{ width: 64 }}
disabled={item.open}
status={item.portStatus}
onChange={(e) => portOnchange(e.target.value, item.id)}
/>
</Space.Compact>
</Space>
{!item.open && (
<TrashIcon
className="proxy-list-del-icon"
onClick={() => {
setProxyList(proxyList.filter((i) => i.id !== item.id));
}}
/>
)}
<Switch
checkedChildren="启"
unCheckedChildren="停"
value={item.open}
disabled={
item.hostStatus === "error" ||
item.portStatus === "error" ||
item.host === "" ||
item.port === ""
}
onChange={(checked: boolean) => {
wsc.clearproxy();
const copyProxyList = structuredClone(proxyList);
copyProxyList.forEach((i) => {
if (i.id === item.id) {
i.open = checked;
if (checked) {
wsc.setproxy(item.scheme, item.host, Number(item.port));
}
} else {
i.open = false;
}
});
setProxyList(copyProxyList);
}}
/>
</div>
))
) : (
<div
className="add-list"
onClick={() => {
setProxyList([
{
id: Math.random() + "",
scheme: "http",
host: "127.0.0.1",
port: "8083",
hostStatus: "",
portStatus: "",
open: false,
},
]);
}}
>
<PlusSmIcon className="add-list-icon" />
<span className="add-list-text">添加</span>
</div>
)}
</div>
</div>
);
};