159 lines
5.2 KiB
TypeScript
159 lines
5.2 KiB
TypeScript
|
|
import BusinessTypeSetting from "@/_BusinessTypeSetting/BusinessTypeSetting";
|
|||
|
|
import MainControlData from "@/Common/DataReceived/MainControlData";
|
|||
|
|
import GameManager from "@/modules/GameManager";
|
|||
|
|
import React, { useContext, useEffect, useState } from "react";
|
|||
|
|
import { useNavigate } from "react-router-dom";
|
|||
|
|
import MainControl, { DownloadForm } from "../Common/MainControl/MainControl";
|
|||
|
|
import CSMessage from "../Common/Message/CSMessage";
|
|||
|
|
import { GameItemsContext } from "../context/GameItemsContext";
|
|||
|
|
import { AccountLoginRequest, CommonAccountResponse, LineLoginRequest } from "../define/Request/AccountRequest";
|
|||
|
|
import { CoroutineV2 } from "../Engine/CatanEngine/CoroutineV2/CoroutineV2";
|
|||
|
|
import { INetResponse } from "../Engine/CatanEngine/NetManagerV2/Core/INetResponse";
|
|||
|
|
|
|||
|
|
export default function LoginPage() {
|
|||
|
|
const navigate = useNavigate();
|
|||
|
|
const { player, setPlayer } = useContext(GameItemsContext);
|
|||
|
|
|
|||
|
|
const [server, setServer] = useState("https://dev.lybobet.com");
|
|||
|
|
const [port, setPort] = useState("9005");
|
|||
|
|
const [token, setToken] = useState("");
|
|||
|
|
const [loading, setLoading] = useState(false);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (!MainControl.Instance) new MainControl();
|
|||
|
|
new MainControlData();
|
|||
|
|
new GameManager();
|
|||
|
|
const savedToken = localStorage.getItem("token");
|
|||
|
|
if (savedToken) setToken(savedToken);
|
|||
|
|
|
|||
|
|
// DownloadForm
|
|||
|
|
MainControl.DownloadForm(DownloadForm.FormType.Formread)
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
const handleChange = (setter: any) => (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) =>
|
|||
|
|
setter(e.target.value);
|
|||
|
|
|
|||
|
|
const onClickLogin = async () => {
|
|||
|
|
if (!server) return CSMessage.CreateYesMsg("請輸入 server");
|
|||
|
|
if (!port) return CSMessage.CreateYesMsg("請輸入 port");
|
|||
|
|
if (!token) return CSMessage.CreateYesMsg("請輸入 token");
|
|||
|
|
if (loading) return;
|
|||
|
|
|
|||
|
|
setLoading(true);
|
|||
|
|
BusinessTypeSetting.UseHost = server;
|
|||
|
|
BusinessTypeSetting.UsePort = +port;
|
|||
|
|
CoroutineV2.Single(login()).Start();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function* login() {
|
|||
|
|
try {
|
|||
|
|
localStorage.setItem("token", token);
|
|||
|
|
yield* MainControl.Instance.ConnectAsync(BusinessTypeSetting.UseHost, BusinessTypeSetting.UsePort);
|
|||
|
|
yield* registerLineLogin();
|
|||
|
|
} finally {
|
|||
|
|
setLoading(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function* registerLineLogin() {
|
|||
|
|
const req = new LineLoginRequest(token);
|
|||
|
|
yield req.SendAsync(true);
|
|||
|
|
const resp: INetResponse<CommonAccountResponse> = req.Result;
|
|||
|
|
|
|||
|
|
if (!resp.IsValid) {
|
|||
|
|
if (resp.Status !== 12) CSMessage.CreateYesMsg("Line Info Error. Error Code: " + resp.Status);
|
|||
|
|
else console.warn("LINE帳號無綁定");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yield* serverAccountLogin(resp.Data.id, resp.Data.pw);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function* serverAccountLogin(a: string, pw: string, partner: string | null = null): IterableIterator<any> {
|
|||
|
|
const hasAP = a && a !== "null" && a !== "undefined" && pw && pw !== "null" && pw !== "undefined";
|
|||
|
|
if (!hasAP) return CSMessage.CreateYesMsg("沒有帳號或密碼.請確認回傳接值.");
|
|||
|
|
|
|||
|
|
const req = new AccountLoginRequest(a, pw, partner);
|
|||
|
|
yield req.SendAsync(true);
|
|||
|
|
const resp: INetResponse<any> = req.Result;
|
|||
|
|
|
|||
|
|
if (!resp.IsValid) return CSMessage.CreateYesMsg("Login Account Error! Error Code : " + resp.Status);
|
|||
|
|
|
|||
|
|
setPlayer({ ...player, ...resp.Data, token });
|
|||
|
|
navigate("/lobby");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ====== inline CSS ======
|
|||
|
|
const containerStyle: React.CSSProperties = {
|
|||
|
|
height: "100vh",
|
|||
|
|
display: "flex",
|
|||
|
|
justifyContent: "center",
|
|||
|
|
alignItems: "center",
|
|||
|
|
background: "transparent",
|
|||
|
|
padding: "16px",
|
|||
|
|
color: "#000000", // 文字黑色
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const boxStyle: React.CSSProperties = {
|
|||
|
|
background: "white", // 卡片內部保持白色
|
|||
|
|
padding: "24px",
|
|||
|
|
borderRadius: "16px",
|
|||
|
|
width: "100%",
|
|||
|
|
maxWidth: "400px",
|
|||
|
|
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|||
|
|
display: "flex",
|
|||
|
|
flexDirection: "column",
|
|||
|
|
gap: "16px",
|
|||
|
|
color: "#000000", // 卡片內文字黑色
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const inputStyle: React.CSSProperties = {
|
|||
|
|
width: "100%",
|
|||
|
|
padding: "12px",
|
|||
|
|
borderRadius: "12px",
|
|||
|
|
border: "1px solid #d9d9d9",
|
|||
|
|
fontSize: "1rem",
|
|||
|
|
color: "#000000", // 輸入文字黑色
|
|||
|
|
backgroundColor: "#ffffff", // 輸入框白色
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const buttonStyle: React.CSSProperties = {
|
|||
|
|
width: "100%",
|
|||
|
|
padding: "12px",
|
|||
|
|
borderRadius: "12px",
|
|||
|
|
border: "none",
|
|||
|
|
backgroundColor: loading ? "#a0a0a0" : "#1890ff",
|
|||
|
|
color: "white",
|
|||
|
|
cursor: loading ? "not-allowed" : "pointer",
|
|||
|
|
fontSize: "1rem",
|
|||
|
|
transition: "all 0.3s",
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div style={containerStyle}>
|
|||
|
|
<div style={boxStyle}>
|
|||
|
|
<h1 style={{ textAlign: "center", fontSize: "1.8rem", margin: 0 }}>登入</h1>
|
|||
|
|
|
|||
|
|
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
|
|||
|
|
<label>Server:</label>
|
|||
|
|
<input style={inputStyle} value={server} onChange={handleChange(setServer)} placeholder="例如:http://192.168.1.10" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
|
|||
|
|
<label>Port:</label>
|
|||
|
|
<input style={inputStyle} value={port} onChange={handleChange(setPort)} placeholder="9005" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
|
|||
|
|
<label>Token:</label>
|
|||
|
|
<textarea style={{ ...inputStyle, height: "80px" }} value={token} onChange={handleChange(setToken)} placeholder="輸入 Token" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<button style={buttonStyle} onClick={onClickLogin} disabled={loading}>
|
|||
|
|
{loading ? "登入中..." : "登入"}
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|