Compare commits

..

9 Commits

Author SHA1 Message Date
john 47bc37ac2c Merge tag '1.0.2' into dev
v1.0.2 1.0.2
2024-06-03 18:44:10 +08:00
john 101fe2bb10 Merge branch 'release/1.0.2' 2024-06-03 18:44:07 +08:00
john b90d388e1f Merge tag 'v1.0.1-issue' into dev
v1.0.1-issue v1.0.1-issue
2024-06-03 18:43:16 +08:00
john 0140ed789a Merge branch 'hotfix/v1.0.1-issue' 2024-06-03 18:43:13 +08:00
john d4a96614b3 🐞 fix:
修复翻译
2024-06-03 18:42:17 +08:00
john cc0f5e2bf5 🐞 fix:
1、去掉接口language参数
2、修复Accept-Language参数
3、手机号校验
4、全局语言标识
2024-06-03 18:37:13 +08:00
john 8e7625c2be Merge tag '1.0.1' into dev
v1.0.1 1.0.1
2024-06-03 14:43:13 +08:00
john e4ad56be66 Merge branch 'release/1.0.1' 2024-06-03 14:42:56 +08:00
john 007c207950 🐞 fix:
添加版本号
2024-06-03 14:42:20 +08:00
8 changed files with 133 additions and 92 deletions

View File

@ -1,7 +1,7 @@
{
"name": "neer-app-h5",
"private": true,
"version": "0.0.0",
"version": "1.0.1",
"type": "module",
"scripts": {
"dev": "vite",

View File

@ -1,8 +1,10 @@
import axios, { AxiosRequestConfig, AxiosRequestHeaders } from 'axios';
import axios, { AxiosRequestConfig, AxiosRequestHeaders } from "axios";
//基础URLaxios将会自动拼接在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,7 +13,7 @@ const service = axios.create({
timeout,
baseURL,
//如需要携带cookie 该值需设为true
withCredentials: true
withCredentials: true,
});
// 统一请求拦截,可配置自定义 headers 例如 language、token 等
service.interceptors.request.use(
@ -22,23 +24,26 @@ service.interceptors.request.use(
}
// 配置自定义请求头
const customHeaders: Partial<AxiosRequestHeaders> = {
language: 'zh-cn',
// 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,65 +52,74 @@ 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 !== 200 && data.code !== 0) {
//特定状态码 处理特定的需求
if(data.code == 401){
console.log('登录异常,执行登出...');
if (data.code == 401) {
console.log("登录异常,执行登出...");
}
const e = JSON.stringify(data);
console.log(`请求错误:${e}`)
console.log(`请求错误:${e}`);
//数据请求错误 使用reject将错误返回
reject(data);
}else{
} else {
//数据请求正确 使用resolve将结果返回
resolve(res as T);
}
}).catch(error => {
})
.catch((error) => {
const e = JSON.stringify(error);
console.log(`网络错误:${e}`)
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),
};
// 导出至外层,方便统一使用

View File

@ -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 () => {

View File

@ -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">

View File

@ -19,5 +19,6 @@
"Official Website": "官方網站",
"Download": "下載",
"send successfully": "發送成功",
"Send failure": "發送失敗"
"Send failure": "發送失敗",
"Invalid phone number": "無效手機號碼"
}

View File

@ -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",
"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"
"Official Website": "Official Website",
"Download": "Download",
"send successfully": "send successfully",
"Send failure": "Send failure",
"Invalid phone number": "Invalid phone number"
}

View File

@ -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

View File

@ -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}
})
previousPathName: "/",
UpdatePreviousPathName: (url) =>
set((state) => {
return { ...state, previousPathName: url };
}),
Lang: "en-US",
UpdateLang: (Lang) => {
set((state) => {
return { ...state, Lang };
});
},
}));
export default useUserStore;