Compare commits
9 Commits
bc75c7885c
...
47bc37ac2c
Author | SHA1 | Date |
---|---|---|
john | 47bc37ac2c | |
john | 101fe2bb10 | |
john | b90d388e1f | |
john | 0140ed789a | |
john | d4a96614b3 | |
john | cc0f5e2bf5 | |
john | 8e7625c2be | |
john | e4ad56be66 | |
john | 007c207950 |
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "neer-app-h5",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"version": "1.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import axios, { AxiosRequestConfig, AxiosRequestHeaders } from 'axios';
|
||||
import axios, { AxiosRequestConfig, AxiosRequestHeaders } from "axios";
|
||||
|
||||
//基础URL,axios将会自动拼接在url前
|
||||
//process.env.NODE_ENV 判断是否为开发环境 根据不同环境使用不同的baseURL 方便调试
|
||||
const baseURL = import.meta.env.DEV ? import.meta.env.VITE_API_URL : import.meta.env.VITE_API_URL;
|
||||
const baseURL = import.meta.env.DEV
|
||||
? import.meta.env.VITE_API_URL
|
||||
: import.meta.env.VITE_API_URL;
|
||||
//默认请求超时时间
|
||||
const timeout = 30000;
|
||||
|
||||
|
@ -11,34 +13,37 @@ const service = axios.create({
|
|||
timeout,
|
||||
baseURL,
|
||||
//如需要携带cookie 该值需设为true
|
||||
withCredentials: true
|
||||
withCredentials: true,
|
||||
});
|
||||
// 统一请求拦截,可配置自定义 headers 例如 language、token 等
|
||||
service.interceptors.request.use(
|
||||
(config: any): any => {
|
||||
// 确保 headers 对象存在
|
||||
// 确保 headers 对象存在
|
||||
if (!config.headers) {
|
||||
config.headers = {};
|
||||
}
|
||||
// 配置自定义请求头
|
||||
const customHeaders: Partial<AxiosRequestHeaders> = {
|
||||
language: 'zh-cn',
|
||||
const customHeaders: Partial<AxiosRequestHeaders> = {
|
||||
// language: "zh-cn",
|
||||
// 这里可以添加其他自定义头信息,例如 token
|
||||
};
|
||||
|
||||
// 合并自定义头信息到 config.headers 中
|
||||
config.headers = { ...config.headers, ...customHeaders } as AxiosRequestHeaders;
|
||||
config.headers = {
|
||||
...config.headers,
|
||||
...customHeaders,
|
||||
} as AxiosRequestHeaders;
|
||||
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
(error) => {
|
||||
console.log(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
//axios返回格式
|
||||
interface axiosTypes<T>{
|
||||
interface axiosTypes<T> {
|
||||
data: T;
|
||||
status: number;
|
||||
statusText: string;
|
||||
|
@ -47,66 +52,75 @@ interface axiosTypes<T>{
|
|||
//后台响应数据格式
|
||||
//###该接口用于规定后台返回的数据格式,意为必须携带code、msg以及result
|
||||
//###而result的数据格式 由外部提供。如此即可根据不同需求,定制不同的数据格式
|
||||
interface responseTypes<T>{
|
||||
code: number,
|
||||
msg: string,
|
||||
result: T
|
||||
interface responseTypes<T> {
|
||||
code: number;
|
||||
msg: string;
|
||||
result: T;
|
||||
}
|
||||
|
||||
//核心处理代码 将返回一个promise 调用then将可获取响应的业务数据
|
||||
const requestHandler = <T>(method: 'get' | 'post' | 'put' | 'delete', url: string, params: object = {}, config: AxiosRequestConfig = {}): Promise<T> => {
|
||||
const requestHandler = <T>(
|
||||
method: "get" | "post" | "put" | "delete",
|
||||
url: string,
|
||||
params: object = {},
|
||||
config: AxiosRequestConfig = {}
|
||||
): Promise<T> => {
|
||||
let response: Promise<axiosTypes<responseTypes<T>>>;
|
||||
switch(method){
|
||||
case 'get':
|
||||
response = service.get(url, {params: { ...params }, ...config});
|
||||
switch (method) {
|
||||
case "get":
|
||||
response = service.get(url, { params: { ...params }, ...config });
|
||||
break;
|
||||
case 'post':
|
||||
response = service.post(url, {...params}, {...config});
|
||||
case "post":
|
||||
response = service.post(url, { ...params }, { ...config });
|
||||
break;
|
||||
case 'put':
|
||||
response = service.put(url, {...params}, {...config});
|
||||
case "put":
|
||||
response = service.put(url, { ...params }, { ...config });
|
||||
break;
|
||||
case 'delete':
|
||||
response = service.delete(url, {params: { ...params }, ...config});
|
||||
case "delete":
|
||||
response = service.delete(url, { params: { ...params }, ...config });
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
response.then(res => {
|
||||
//业务代码 可根据需求自行处理
|
||||
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 T);
|
||||
}
|
||||
|
||||
}).catch(error => {
|
||||
const e = JSON.stringify(error);
|
||||
console.log(`网络错误:${e}`)
|
||||
reject(error);
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
const e = JSON.stringify(error);
|
||||
console.log(`网络错误:${e}`);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 使用 request 统一调用,包括封装的get、post、put、delete等方法
|
||||
const request = {
|
||||
get: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('get', url, params, config),
|
||||
post: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('post', url, params, config),
|
||||
put: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('put', url, params, config),
|
||||
delete: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('delete', url, params, config)
|
||||
get: <T>(url: string, params?: object, config?: AxiosRequestConfig) =>
|
||||
requestHandler<T>("get", url, params, config),
|
||||
post: <T>(url: string, params?: object, config?: AxiosRequestConfig) =>
|
||||
requestHandler<T>("post", url, params, config),
|
||||
put: <T>(url: string, params?: object, config?: AxiosRequestConfig) =>
|
||||
requestHandler<T>("put", url, params, config),
|
||||
delete: <T>(url: string, params?: object, config?: AxiosRequestConfig) =>
|
||||
requestHandler<T>("delete", url, params, config),
|
||||
};
|
||||
|
||||
// 导出至外层,方便统一使用
|
||||
export { request };
|
||||
export { request };
|
||||
|
|
|
@ -10,6 +10,7 @@ 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";
|
||||
|
||||
function EmailForm() {
|
||||
const formRef = useRef<FormInstance>(null);
|
||||
|
@ -20,10 +21,11 @@ function EmailForm() {
|
|||
const [authCode, setAuthCode] = useState("");
|
||||
const [shareCode, setShareCode] = useState("");
|
||||
const [remainingTime, setRemainingTime] = useState(0);
|
||||
const { Lang } = useUserStore();
|
||||
|
||||
const config = {
|
||||
headers: {
|
||||
"Accept-Language": navigator.language,
|
||||
"Accept-Language": Lang,
|
||||
},
|
||||
};
|
||||
const sendVerificationCode = async () => {
|
||||
|
|
|
@ -20,6 +20,7 @@ function PhoneForm() {
|
|||
CurrentPhoneNumber,
|
||||
UpdateCurrentPhoneNumber,
|
||||
UpdatePreviousPathName,
|
||||
Lang,
|
||||
} = useUserStore();
|
||||
|
||||
const getShareCode = (url: string) => {
|
||||
|
@ -51,7 +52,7 @@ function PhoneForm() {
|
|||
};
|
||||
const config = {
|
||||
headers: {
|
||||
"Accept-Language": navigator.language,
|
||||
"Accept-Language": Lang,
|
||||
},
|
||||
};
|
||||
const sendVerificationCode = async () => {
|
||||
|
@ -153,6 +154,7 @@ function PhoneForm() {
|
|||
console.warn(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
name="form"
|
||||
|
@ -177,6 +179,14 @@ function PhoneForm() {
|
|||
name="account"
|
||||
rules={[
|
||||
{ required: true, message: t("Please enter your phone number") },
|
||||
{
|
||||
validator: (_, v) => {
|
||||
if (v != "" && !/^\d+$/.test(v)) {
|
||||
return Promise.reject(new Error(t("Invalid phone number")));
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<div className="phone-box">
|
||||
|
|
|
@ -19,5 +19,6 @@
|
|||
"Official Website": "官方網站",
|
||||
"Download": "下載",
|
||||
"send successfully": "發送成功",
|
||||
"Send failure": "發送失敗"
|
||||
}
|
||||
"Send failure": "發送失敗",
|
||||
"Invalid phone number": "無效手機號碼"
|
||||
}
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
{
|
||||
"E-mail": "E-mail",
|
||||
"phone":"phone",
|
||||
"Please enter your email address":"Please enter your email address",
|
||||
"Please enter the email verification code":"Please enter the email verification code",
|
||||
"Please enter your phone number":"Please enter your phone number",
|
||||
"Please enter SMS verification code":"Please enter SMS verification code",
|
||||
"Send verification code":"Send verification code",
|
||||
"Please enter the invitation code (optional)":"Please enter the invitation code (optional)",
|
||||
"register":"Register",
|
||||
"If you already have an account":"If you already have an account",
|
||||
"download the APP directly":"download the APP directly",
|
||||
"Continuing to represent you in agreeing to our":"Continuing to represent you in agreeing to our",
|
||||
"Terms of Service":"Terms of Service",
|
||||
"and":"and",
|
||||
"Privacy Policy":"Privacy Policy",
|
||||
"Select country/region":"Select country/region",
|
||||
"seconds": "s",
|
||||
"Official Website":"Official Website",
|
||||
"Download":"Download",
|
||||
"send successfully":"send successfully",
|
||||
"Send failure":"Send failure"
|
||||
"phone": "phone",
|
||||
"Please enter your email address": "Please enter your email address",
|
||||
"Please enter the email verification code": "Please enter the email verification code",
|
||||
"Please enter your phone number": "Please enter your phone number",
|
||||
"Please enter SMS verification code": "Please enter SMS verification code",
|
||||
"Send verification code": "Send verification code",
|
||||
"Please enter the invitation code (optional)": "Please enter the invitation code (optional)",
|
||||
"register": "Register",
|
||||
"If you already have an account": "If you already have an account",
|
||||
"download the APP directly": "download the APP directly",
|
||||
"Continuing to represent you in agreeing to our": "Continuing to represent you in agreeing to our",
|
||||
"Terms of Service": "Terms of Service",
|
||||
"and": "and",
|
||||
"Privacy Policy": "Privacy Policy",
|
||||
"Select country/region": "Select country/region",
|
||||
"seconds": "s",
|
||||
"Official Website": "Official Website",
|
||||
"Download": "Download",
|
||||
"send successfully": "send successfully",
|
||||
"Send failure": "Send failure",
|
||||
"Invalid phone number": "Invalid phone number"
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ function SignIn() {
|
|||
const [selectIndex, setSelectIndex] = useState<number>(0);
|
||||
const { previousPathName, UpdatePreviousPathName } = useUserStore();
|
||||
const navigate = useNavigate();
|
||||
const { UpdateLang } = useUserStore();
|
||||
const handleTabs = (num: number) => {
|
||||
return () => {
|
||||
UpdatePreviousPathName("/");
|
||||
|
@ -70,6 +71,7 @@ function SignIn() {
|
|||
onClick={() => {
|
||||
i18n.changeLanguage("cn");
|
||||
setVisible(false);
|
||||
UpdateLang("zh-TW");
|
||||
}}
|
||||
>
|
||||
中文(繁体)
|
||||
|
@ -80,6 +82,7 @@ function SignIn() {
|
|||
onClick={() => {
|
||||
i18n.changeLanguage("en");
|
||||
setVisible(false);
|
||||
UpdateLang("en-US");
|
||||
}}
|
||||
>
|
||||
English
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
/*
|
||||
* @LastEditors: John
|
||||
* @Date: 2024-01-19 11:31:12
|
||||
* @LastEditTime: 2024-01-25 15:42:25
|
||||
* @LastEditTime: 2024-06-03 14:52:45
|
||||
* @Author: John
|
||||
*/
|
||||
import { create } from "zustand";
|
||||
import { CountryItem } from "../type/SelectCountry";
|
||||
export type LanguageCode = "en-US" | "zh-CN" | "zh-TW" | "ko-KR";
|
||||
|
||||
// 状态管理器
|
||||
export interface UserState {
|
||||
SelectCountry: CountryItem | null;
|
||||
UpdateSelectCountry: (item: CountryItem) => void
|
||||
UpdateSelectCountry: (item: CountryItem) => void;
|
||||
Token: string;
|
||||
UpdateToken: (token: string) => void;
|
||||
CurrentPhoneNumber:string;
|
||||
CurrentPhoneNumber: string;
|
||||
UpdateCurrentPhoneNumber: (number: string) => void;
|
||||
previousPathName:string;
|
||||
UpdatePreviousPathName:(number: string) => void;
|
||||
previousPathName: string;
|
||||
UpdatePreviousPathName: (number: string) => void;
|
||||
Lang: LanguageCode;
|
||||
UpdateLang: (lan: LanguageCode) => void;
|
||||
}
|
||||
|
||||
const useUserStore = create<UserState>()((set) => ({
|
||||
|
@ -30,16 +34,22 @@ const useUserStore = create<UserState>()((set) => ({
|
|||
set((state) => {
|
||||
return { ...state, Token: token };
|
||||
}),
|
||||
CurrentPhoneNumber:'',
|
||||
CurrentPhoneNumber: "",
|
||||
UpdateCurrentPhoneNumber: (val) =>
|
||||
set((state) => {
|
||||
return { ...state, CurrentPhoneNumber: val };
|
||||
}),
|
||||
previousPathName:'/',
|
||||
UpdatePreviousPathName:(url) =>
|
||||
set((state)=>{
|
||||
return {...state,previousPathName:url}
|
||||
})
|
||||
return { ...state, CurrentPhoneNumber: val };
|
||||
}),
|
||||
previousPathName: "/",
|
||||
UpdatePreviousPathName: (url) =>
|
||||
set((state) => {
|
||||
return { ...state, previousPathName: url };
|
||||
}),
|
||||
Lang: "en-US",
|
||||
UpdateLang: (Lang) => {
|
||||
set((state) => {
|
||||
return { ...state, Lang };
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
export default useUserStore;
|
||||
|
|
Loading…
Reference in New Issue