diff --git a/.env.development b/.env.development
index a7519b9..a5df16f 100644
--- a/.env.development
+++ b/.env.development
@@ -1,4 +1,10 @@
+###
+ # @LastEditors: John
+ # @Date: 2024-06-03 14:42:56
+ # @LastEditTime: 2024-06-06 17:31:31
+ # @Author: John
+###
VITE_APP_DEV = 'dev-api'
-# VITE_API_URL = 'http://192.168.10.166:8096'
+VITE_API_URL = 'http://192.168.10.166:8097'
# VITE_API_URL = 'https://8.217.122.133:10020'
-VITE_API_URL = 'https://api.pineer.cc'
\ No newline at end of file
+# VITE_API_URL = 'https://api.pineer.cc'
\ No newline at end of file
diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz
index d60d84e..843388b 100644
Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ
diff --git a/index.html b/index.html
index 1228873..ac811a3 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
@@ -9,7 +9,10 @@
-
+
Pioneer
diff --git a/package.json b/package.json
index c84da9f..7c2f1b8 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@use-gesture/react": "^10.3.1",
"antd-mobile": "^5.34.0",
"axios": "^1.6.7",
"i18next": "^23.7.20",
diff --git a/src/App.css b/src/App.css
index b73928a..6372346 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,6 +1,9 @@
#root {
- /* max-width: 1280px; */
- /* margin: 0 auto; */
padding: 2rem;
text-align: center;
-}
\ No newline at end of file
+}
+
+.adm-center-popup-wrap {
+ min-width: fit-content !important;
+ max-width: fit-content !important;
+}
diff --git a/src/App.tsx b/src/App.tsx
index 5bcf1e0..b91a2f2 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,7 +1,7 @@
/*
* @LastEditors: John
* @Date: 2024-05-22 18:06:14
- * @LastEditTime: 2024-05-22 18:45:10
+ * @LastEditTime: 2024-06-06 16:49:46
* @Author: John
*/
import "./App.css";
@@ -11,6 +11,7 @@ import SignIn from "./pages/SignIn";
import Download from "./pages/Download";
import SelectCountry from "./pages/SelectCountry";
import { useTranslation } from "react-i18next";
+import Auth from "./pages/Auth";
function App() {
const { i18n } = useTranslation();
@@ -25,6 +26,7 @@ function App() {
+
diff --git a/src/api/index.ts b/src/api/index.ts
index 0be8c5d..7cee2dd 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -1,29 +1,52 @@
import { request } from "./request";
-import { AxiosRequestConfig } from 'axios';
+import { AxiosRequestConfig } from "axios";
+
+export type SendCodeResType = {
+ sms?: boolean;
+ captcha?: {
+ bigWidth: number;
+ bigHeight: number;
+ bigImageBase64: string;
+ bigImage: null;
+ posY: number;
+ posX: null;
+ smallWidth: number;
+ smallHeight: number;
+ smallImageBase64: string;
+ smallImage: null;
+ };
+};
//发送验证码
-export const sendCode = (params: {
- areaCode?: string; // 区号,只有手机号才有
- account: string; // 账号(邮箱或手机号)
- status: 1 | 2; // 1=登录 2=注册
- signature: string;
- timestamp: string;
-},config:AxiosRequestConfig) =>
- request.get("/api/account/sendVerificationCode", params, {
+export const sendCode = (
+ params: {
+ areaCode?: string; // 区号,只有手机号才有
+ account: string; // 账号(邮箱或手机号)
+ status: 1 | 2; // 1=登录 2=注册
+ signature: string;
+ timestamp: string;
+ posX?: number;
+ },
+ config: AxiosRequestConfig
+) =>
+ request.get("/api/account/sendVerificationCode", params, {
timeout: 15000,
- ...config
+ ...config,
});
//注册
-export const signUp = (params: {
- account: string; // account
- area?: string; // 顶级区域:朝鲜/平壤、中国/广东
- areaCode?: string; // 区号,只有手机号才有
- authCode: string; // 验证码
- district?: string; // 二级区域:具体的区域
- shareCode: string; // invitation code
- userName: string; // 用户名称
-},config:AxiosRequestConfig) =>
+export const signUp = (
+ params: {
+ account: string; // account
+ area?: string; // 顶级区域:朝鲜/平壤、中国/广东
+ areaCode?: string; // 区号,只有手机号才有
+ authCode: string; // 验证码
+ district?: string; // 二级区域:具体的区域
+ shareCode: string; // invitation code
+ userName: string; // 用户名称
+ },
+ config: AxiosRequestConfig
+) =>
request.post("/api/account/signUp", params, {
timeout: 15000,
- ...config
- });
\ No newline at end of file
+ ...config,
+ });
diff --git a/src/api/request.ts b/src/api/request.ts
index e6932c2..ada7700 100644
--- a/src/api/request.ts
+++ b/src/api/request.ts
@@ -32,6 +32,7 @@ service.interceptors.request.use(
config.headers = {
...config.headers,
...customHeaders,
+ appVersion: "1.0.4",
} as AxiosRequestHeaders;
return config;
@@ -55,7 +56,7 @@ interface axiosTypes {
interface responseTypes {
code: number;
msg: string;
- result: T;
+ data: T | null;
}
//核心处理代码 将返回一个promise 调用then将可获取响应的业务数据
@@ -64,7 +65,7 @@ const requestHandler = (
url: string,
params: object = {},
config: AxiosRequestConfig = {}
-): Promise => {
+): Promise>> => {
let response: Promise>>;
switch (method) {
case "get":
@@ -81,26 +82,28 @@ const requestHandler = (
break;
}
- return new Promise((resolve, reject) => {
+ return new Promise>>((resolve, reject) => {
response
.then((res) => {
//业务代码 可根据需求自行处理
- const data = res.data;
- if (data.code !== 200 && data.code !== 0) {
- //特定状态码 处理特定的需求
- if (data.code == 401) {
- console.log("登录异常,执行登出...");
- }
+ // const data = res.data;
+ // if (data.code !== 200 && data.code !== 0) {
+ // //特定状态码 处理特定的需求
+ // if (data.code == 401) {
+ // console.log("登录异常,执行登出...");
+ // }
- const e = JSON.stringify(data);
- console.log(`请求错误:${e}`);
- //数据请求错误 使用reject将错误返回
- reject(data);
- } else {
- //数据请求正确 使用resolve将结果返回
- resolve(res as T);
- }
+ // const e = JSON.stringify(data);
+ // console.log(`请求错误:${e}`);
+ // //数据请求错误 使用reject将错误返回
+ // reject(data);
+ // } else {
+ // //数据请求正确 使用resolve将结果返回
+ // resolve(res as axiosTypes>);
+ // }
+
+ resolve(res as axiosTypes>);
})
.catch((error) => {
const e = JSON.stringify(error);
diff --git a/src/components/EmailForm.tsx b/src/components/EmailForm.tsx
index f7b7934..011c879 100644
--- a/src/components/EmailForm.tsx
+++ b/src/components/EmailForm.tsx
@@ -1,16 +1,17 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useState, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
-import { Form, Input, Button } from "antd-mobile";
+import { Form, Input, Button, Modal } from "antd-mobile";
import "../pages/SignIn.scss";
import { useCountdown } from "../hooks/useCountdown";
import { sendCode, signUp } from "../api";
-import { sendCodeTypes, signUpTypes, ErrorType } from "../type/SignIn";
+import { signUpTypes, ErrorType } from "../type/SignIn";
import { Toast } from "antd-mobile";
import { useNavigate } from "react-router-dom";
import { Md5 } from "ts-md5";
import { FormInstance } from "antd-mobile/es/components/form";
import useUserStore from "../store/user";
+import SilderVertify, { SilderVertify_handleType } from "./SilderVertify";
function EmailForm() {
const formRef = useRef(null);
@@ -22,7 +23,7 @@ function EmailForm() {
const [shareCode, setShareCode] = useState("");
const [remainingTime, setRemainingTime] = useState(0);
const { Lang } = useUserStore();
-
+ const SilderVertifyRef = useRef(null);
const config = {
headers: {
"Accept-Language": Lang,
@@ -33,33 +34,59 @@ function EmailForm() {
if (email === "") {
return;
}
- const timestamp = `${new Date().getTime()}`;
- const res = await sendCode(
- {
- account: email,
- areaCode: "",
- status: 2,
- signature: Md5.hashStr(`Neer${email},${2},${timestamp}GetCode`),
- timestamp,
- },
- config
- );
- console.log("res", res);
- if (res.status === 200 && res.data.data.sms) {
- Toast.show({
- content: t("send successfully"),
- afterClose: () => {
- start(60 * 1000);
- },
- });
- } else {
- Toast.show({
- content: t("Send failure"),
- afterClose: () => {
- // start(60 * 1000);
- },
- });
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
+ Toast.show({ content: t("Invalid email") });
+ return;
}
+ Modal.show({
+ content: (
+ <>
+ {
+ const timestamp = `${new Date().getTime()}`;
+ const res = await sendCode(
+ {
+ account: email,
+ areaCode: "",
+ status: 2,
+ signature: Md5.hashStr(
+ `Neer${email},${2},${timestamp}GetCode`
+ ),
+ timestamp,
+ posX: pox,
+ },
+ config
+ );
+ console.log("res", res);
+ if (res.status === 200 && res.data.data?.sms) {
+ Toast.show({
+ content: t("send successfully"),
+ afterClose: () => {
+ start(60 * 1000);
+ },
+ });
+ Modal.clear();
+ } else {
+ Toast.show({
+ content: res.data.msg,
+ afterClose: () => {
+ // start(60 * 1000);
+ },
+ });
+ if (res.data.code == 1014) {
+ SilderVertifyRef.current?._init();
+ return;
+ }
+ Modal.clear();
+ }
+ }}
+ />
+ >
+ ),
+ closeOnMaskClick: true,
+ });
} catch (error: unknown) {
// 检查 error 是否是 ErrorType 类型
if (typeof error === "object" && error !== null && "msg" in error) {
@@ -99,8 +126,7 @@ function EmailForm() {
config
);
console.log("res", res);
- if (res.status === 200 && res.data.data.token) {
- console.log(111);
+ if (res.status === 200 && res.data.data?.token) {
Toast.show({
content: res.data.msg,
});
diff --git a/src/components/PhoneForm.tsx b/src/components/PhoneForm.tsx
index 84b4292..5ac54fe 100644
--- a/src/components/PhoneForm.tsx
+++ b/src/components/PhoneForm.tsx
@@ -1,15 +1,23 @@
+/*
+ * @LastEditors: John
+ * @Date: 2024-06-03 18:43:16
+ * @LastEditTime: 2024-06-06 18:59:13
+ * @Author: John
+ */
import { useState, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
-import { Form, Input, Button } from "antd-mobile";
+import { Form, Input, Button, Modal } from "antd-mobile";
import { useNavigate } from "react-router-dom";
import "../pages/SignIn.scss";
import useUserStore from "../store/user.ts";
import { useCountdown } from "../hooks/useCountdown";
import { sendCode, signUp } from "../api";
-import { sendCodeTypes, signUpTypes, ErrorType } from "../type/SignIn";
+import { signUpTypes, ErrorType } from "../type/SignIn";
import { Toast } from "antd-mobile";
import { Md5 } from "ts-md5";
import { FormInstance } from "antd-mobile/es/components/form/form";
+import SilderVertify, { SilderVertify_handleType } from "./SilderVertify.tsx";
+const defaultAreaCode = "+1";
function PhoneForm() {
const formRef = useRef(null);
const { t } = useTranslation();
@@ -38,10 +46,10 @@ function PhoneForm() {
return "";
};
- const defaultAreaCode = "+1";
const [authCode, setAuthCode] = useState("");
const [shareCode, setShareCode] = useState("");
const [remainingTime, setRemainingTime] = useState(0);
+ const SilderVertifyRef = useRef(null);
const gotoSelectCountry = () => {
UpdatePreviousPathName("/");
@@ -60,36 +68,55 @@ function PhoneForm() {
if (CurrentPhoneNumber === "") {
return;
}
- const timestamp = `${new Date().getTime()}`;
- const res = await sendCode(
- {
- account: CurrentPhoneNumber,
- areaCode: SelectCountry?.code || defaultAreaCode,
- status: 2,
- signature: Md5.hashStr(
- `Neer${CurrentPhoneNumber},${2},${timestamp}GetCode`
- ),
- timestamp,
- },
- config
- );
- console.log("res", res);
- if (res.status === 200 && res.data.data.sms) {
- console.log(111);
- Toast.show({
- content: t("send successfully"),
- afterClose: () => {
- start(60 * 1000);
- },
- });
- } else {
- Toast.show({
- content: t("Send failure"),
- afterClose: () => {
- // start(60 * 1000);
- },
- });
- }
+
+ Modal.show({
+ content: (
+ <>
+ {
+ const timestamp = `${new Date().getTime()}`;
+ const res = await sendCode(
+ {
+ account: CurrentPhoneNumber,
+ areaCode: SelectCountry?.code || defaultAreaCode,
+ status: 2,
+ signature: Md5.hashStr(
+ `Neer${CurrentPhoneNumber},${2},${timestamp}GetCode`
+ ),
+ timestamp,
+ posX: pox,
+ },
+ config
+ );
+ if (res.status === 200 && res.data.data?.sms) {
+ Toast.show({
+ content: t("send successfully"),
+ afterClose: () => {
+ start(60 * 1000);
+ },
+ });
+ Modal.clear();
+ } else {
+ Toast.show({
+ content: res.data.msg,
+ afterClose: () => {
+ // start(60 * 1000);
+ },
+ });
+ if (res.data.code == 1014) {
+ SilderVertifyRef.current?._init();
+ return;
+ }
+ Modal.clear();
+ }
+ }}
+ />
+ >
+ ),
+ closeOnMaskClick: true,
+ });
} catch (error: unknown) {
// 检查 error 是否是 ErrorType 类型
if (typeof error === "object" && error !== null && "msg" in error) {
@@ -127,8 +154,7 @@ function PhoneForm() {
},
config
);
- console.log("res", res);
- if (res.status === 200 && res.data.data.token) {
+ if (res.status === 200 && res.data.data?.token) {
Toast.show({
content: res.data.msg,
});
diff --git a/src/components/SilderVertify.tsx b/src/components/SilderVertify.tsx
new file mode 100644
index 0000000..e443200
--- /dev/null
+++ b/src/components/SilderVertify.tsx
@@ -0,0 +1,150 @@
+import { useDrag } from "@use-gesture/react";
+import { forwardRef, useState, useImperativeHandle, useEffect } from "react";
+import { Md5 } from "ts-md5";
+import { sendCode } from "../api";
+import useUserStore from "../store/user";
+import { useTranslation } from "react-i18next";
+
+/*
+ * @LastEditors: John
+ * @Date: 2024-06-06 16:41:24
+ * @LastEditTime: 2024-06-06 21:07:00
+ * @Author: John
+ */
+export type SilderVertify_handleType = {
+ _init: () => void;
+};
+const SilderVertify = forwardRef<
+ SilderVertify_handleType,
+ {
+ account: string;
+ onFinish: (pox: number) => Promise;
+ }
+>(function ({ onFinish, account }, ref) {
+ const [offsetX, setOffsetX] = useState(0);
+ // Set the drag hook and define component movement based on gesture data.
+ const bind = useDrag(async ({ event, down, movement: [mx, _] }) => {
+ event.preventDefault();
+ // console.log(down, [mx, my]);
+ if (down) {
+ if (mx <= 0) return;
+ if (mx >= 280) return;
+ setOffsetX(mx);
+ } else {
+ await onFinish(parseInt(`${mx}`));
+ setOffsetX(0);
+ }
+ });
+
+ const [bigImage, setBigImage] = useState("");
+ const [smallImage, setSmallImage] = useState("");
+ const [smallImageY, setSmallImageY] = useState(0);
+ const { SelectCountry, Lang } = useUserStore();
+ const { t } = useTranslation();
+ useImperativeHandle(ref, () => {
+ return {
+ _init() {
+ init();
+ },
+ };
+ });
+
+ const config = {
+ headers: {
+ "Accept-Language": Lang,
+ },
+ };
+ async function init() {
+ setOffsetX(0);
+ const timestamp = `${new Date().getTime()}`;
+ const res = await sendCode(
+ {
+ account: account,
+ areaCode: SelectCountry?.code || "+1",
+ status: 2,
+ signature: Md5.hashStr(`Neer${account},${2},${timestamp}GetCode`),
+ timestamp,
+ },
+ config
+ );
+ if (res.status == 200 && res.data.code == 0) {
+ setBigImage(res.data.data?.captcha?.bigImageBase64 || "");
+ setSmallImage(res.data.data?.captcha?.smallImageBase64 || "");
+ setSmallImageY(res.data.data?.captcha?.posY || 0);
+ }
+ }
+ useEffect(() => {
+ init();
+
+ return () => {};
+ }, []);
+
+ return (
+
+
{t("Complete security verification")}
+
+
+
+
+
+
+ );
+});
+
+export default SilderVertify;
diff --git a/src/i18n/cn/translation.json b/src/i18n/cn/translation.json
index 6d02926..70c2b96 100644
--- a/src/i18n/cn/translation.json
+++ b/src/i18n/cn/translation.json
@@ -20,5 +20,7 @@
"Download": "下載",
"send successfully": "發送成功",
"Send failure": "發送失敗",
- "Invalid phone number": "無效手機號碼"
+ "Invalid phone number": "無效手機號碼",
+ "Invalid email": "無效電子郵件",
+ "Complete security verification": "完成安全驗證"
}
diff --git a/src/i18n/en/translation.json b/src/i18n/en/translation.json
index e79f857..af36447 100644
--- a/src/i18n/en/translation.json
+++ b/src/i18n/en/translation.json
@@ -20,5 +20,7 @@
"Download": "Download",
"send successfully": "send successfully",
"Send failure": "Send failure",
- "Invalid phone number": "Invalid phone number"
+ "Invalid phone number": "Invalid phone number",
+ "Invalid email": "Invalid email",
+ "Complete security verification": "Complete security verification"
}
diff --git a/src/pages/Auth.tsx b/src/pages/Auth.tsx
new file mode 100644
index 0000000..f8cb4e8
--- /dev/null
+++ b/src/pages/Auth.tsx
@@ -0,0 +1,15 @@
+/*
+ * @LastEditors: John
+ * @Date: 2024-06-06 11:22:50
+ * @LastEditTime: 2024-06-06 11:35:16
+ * @Author: John
+ */
+export default function () {
+ return (
+ <>
+
+ Open My App with Params
+
+ >
+ );
+}
diff --git a/src/pages/SignIn.tsx b/src/pages/SignIn.tsx
index 9a36037..e2d10b4 100644
--- a/src/pages/SignIn.tsx
+++ b/src/pages/SignIn.tsx
@@ -107,14 +107,14 @@ function SignIn() {
className={`tabs-button ${selectIndex === 0 && "selected"}`}
onClick={handleTabs(0)}
>
-
+
{t("E-mail")}
-
+
{t("phone")}
diff --git a/tsconfig.node.json b/tsconfig.node.json
index a381973..9d0aba7 100644
--- a/tsconfig.node.json
+++ b/tsconfig.node.json
@@ -5,7 +5,7 @@
"module": "commonjs",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
- "sourceMap":true
+ "sourceMap": true
},
"include": ["vite.config.ts"]
}
diff --git a/vite.config.ts b/vite.config.ts
index 861b04b..2be9464 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,16 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react-swc'
+/*
+ * @LastEditors: John
+ * @Date: 2024-05-22 18:06:14
+ * @LastEditTime: 2024-06-05 17:41:40
+ * @Author: John
+ */
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
export default defineConfig({
+ server: {
+ host: "192.168.10.167",
+ },
plugins: [react()],
-})
+});
diff --git a/yarn.lock b/yarn.lock
index f39f617..04ffb5f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -612,6 +612,13 @@ __metadata:
languageName: node
linkType: hard
+"@use-gesture/core@npm:10.3.1":
+ version: 10.3.1
+ resolution: "@use-gesture/core@npm:10.3.1"
+ checksum: 10c0/2e3b5c0f7fe26cdb47be3a9c2a58a6a9edafc5b2895b07d2898eda9ab5a2b29fb0098b15597baa0856907b593075cd44cc69bba4785c9cfb7b6fabaa3b52cd3e
+ languageName: node
+ linkType: hard
+
"@use-gesture/react@npm:10.3.0":
version: 10.3.0
resolution: "@use-gesture/react@npm:10.3.0"
@@ -623,6 +630,17 @@ __metadata:
languageName: node
linkType: hard
+"@use-gesture/react@npm:^10.3.1":
+ version: 10.3.1
+ resolution: "@use-gesture/react@npm:10.3.1"
+ dependencies:
+ "@use-gesture/core": "npm:10.3.1"
+ peerDependencies:
+ react: ">= 16.8.0"
+ checksum: 10c0/978da66e4e7c424866ad52eba8fdf0ce93a4c8fc44f8837c7043e68c6a6107cd67e817fffb27f7db2ae871ef2f6addb0c8ddf1586f24c67b7e6aef1646c668cf
+ languageName: node
+ linkType: hard
+
"@vitejs/plugin-react-swc@npm:^3.5.0":
version: 3.5.0
resolution: "@vitejs/plugin-react-swc@npm:3.5.0"
@@ -1565,6 +1583,7 @@ __metadata:
"@types/node": "npm:^20.11.7"
"@types/react": "npm:^18.2.43"
"@types/react-dom": "npm:^18.2.17"
+ "@use-gesture/react": "npm:^10.3.1"
"@vitejs/plugin-react-swc": "npm:^3.5.0"
antd-mobile: "npm:^5.34.0"
axios: "npm:^1.6.7"