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", "name": "neer-app-h5",
"private": true, "private": true,
"version": "0.0.0", "version": "1.0.1",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -1,8 +1,10 @@
import axios, { AxiosRequestConfig, AxiosRequestHeaders } from 'axios'; import axios, { AxiosRequestConfig, AxiosRequestHeaders } from "axios";
//基础URLaxios将会自动拼接在url前 //基础URLaxios将会自动拼接在url前
//process.env.NODE_ENV 判断是否为开发环境 根据不同环境使用不同的baseURL 方便调试 //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; const timeout = 30000;
@ -11,7 +13,7 @@ const service = axios.create({
timeout, timeout,
baseURL, baseURL,
//如需要携带cookie 该值需设为true //如需要携带cookie 该值需设为true
withCredentials: true withCredentials: true,
}); });
// 统一请求拦截,可配置自定义 headers 例如 language、token 等 // 统一请求拦截,可配置自定义 headers 例如 language、token 等
service.interceptors.request.use( service.interceptors.request.use(
@ -22,16 +24,19 @@ service.interceptors.request.use(
} }
// 配置自定义请求头 // 配置自定义请求头
const customHeaders: Partial<AxiosRequestHeaders> = { const customHeaders: Partial<AxiosRequestHeaders> = {
language: 'zh-cn', // language: "zh-cn",
// 这里可以添加其他自定义头信息,例如 token // 这里可以添加其他自定义头信息,例如 token
}; };
// 合并自定义头信息到 config.headers 中 // 合并自定义头信息到 config.headers 中
config.headers = { ...config.headers, ...customHeaders } as AxiosRequestHeaders; config.headers = {
...config.headers,
...customHeaders,
} as AxiosRequestHeaders;
return config; return config;
}, },
error => { (error) => {
console.log(error); console.log(error);
return Promise.reject(error); return Promise.reject(error);
} }
@ -48,64 +53,73 @@ interface axiosTypes<T>{
//###该接口用于规定后台返回的数据格式意为必须携带code、msg以及result //###该接口用于规定后台返回的数据格式意为必须携带code、msg以及result
//###而result的数据格式 由外部提供。如此即可根据不同需求,定制不同的数据格式 //###而result的数据格式 由外部提供。如此即可根据不同需求,定制不同的数据格式
interface responseTypes<T> { interface responseTypes<T> {
code: number, code: number;
msg: string, msg: string;
result: T result: T;
} }
//核心处理代码 将返回一个promise 调用then将可获取响应的业务数据 //核心处理代码 将返回一个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>>>; let response: Promise<axiosTypes<responseTypes<T>>>;
switch (method) { switch (method) {
case 'get': case "get":
response = service.get(url, { params: { ...params }, ...config }); response = service.get(url, { params: { ...params }, ...config });
break; break;
case 'post': case "post":
response = service.post(url, { ...params }, { ...config }); response = service.post(url, { ...params }, { ...config });
break; break;
case 'put': case "put":
response = service.put(url, { ...params }, { ...config }); response = service.put(url, { ...params }, { ...config });
break; break;
case 'delete': case "delete":
response = service.delete(url, { params: { ...params }, ...config }); response = service.delete(url, { params: { ...params }, ...config });
break; break;
} }
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
response.then(res => { response
.then((res) => {
//业务代码 可根据需求自行处理 //业务代码 可根据需求自行处理
const data = res.data; const data = res.data;
if (data.code !== 200 && data.code !== 0) { if (data.code !== 200 && data.code !== 0) {
//特定状态码 处理特定的需求 //特定状态码 处理特定的需求
if (data.code == 401) { if (data.code == 401) {
console.log('登录异常,执行登出...'); console.log("登录异常,执行登出...");
} }
const e = JSON.stringify(data); const e = JSON.stringify(data);
console.log(`请求错误:${e}`) console.log(`请求错误:${e}`);
//数据请求错误 使用reject将错误返回 //数据请求错误 使用reject将错误返回
reject(data); reject(data);
} else { } else {
//数据请求正确 使用resolve将结果返回 //数据请求正确 使用resolve将结果返回
resolve(res as T); resolve(res as T);
} }
})
}).catch(error => { .catch((error) => {
const e = JSON.stringify(error); const e = JSON.stringify(error);
console.log(`网络错误:${e}`) console.log(`网络错误:${e}`);
reject(error); reject(error);
}) });
}) });
} };
// 使用 request 统一调用包括封装的get、post、put、delete等方法 // 使用 request 统一调用包括封装的get、post、put、delete等方法
const request = { const request = {
get: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('get', url, params, config), get: <T>(url: string, params?: object, config?: AxiosRequestConfig) =>
post: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('post', url, params, config), requestHandler<T>("get", url, params, config),
put: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('put', url, params, config), post: <T>(url: string, params?: object, config?: AxiosRequestConfig) =>
delete: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('delete', url, params, config) 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 { useNavigate } from "react-router-dom";
import { Md5 } from "ts-md5"; import { Md5 } from "ts-md5";
import { FormInstance } from "antd-mobile/es/components/form"; import { FormInstance } from "antd-mobile/es/components/form";
import useUserStore from "../store/user";
function EmailForm() { function EmailForm() {
const formRef = useRef<FormInstance>(null); const formRef = useRef<FormInstance>(null);
@ -20,10 +21,11 @@ function EmailForm() {
const [authCode, setAuthCode] = useState(""); const [authCode, setAuthCode] = useState("");
const [shareCode, setShareCode] = useState(""); const [shareCode, setShareCode] = useState("");
const [remainingTime, setRemainingTime] = useState(0); const [remainingTime, setRemainingTime] = useState(0);
const { Lang } = useUserStore();
const config = { const config = {
headers: { headers: {
"Accept-Language": navigator.language, "Accept-Language": Lang,
}, },
}; };
const sendVerificationCode = async () => { const sendVerificationCode = async () => {

View File

@ -20,6 +20,7 @@ function PhoneForm() {
CurrentPhoneNumber, CurrentPhoneNumber,
UpdateCurrentPhoneNumber, UpdateCurrentPhoneNumber,
UpdatePreviousPathName, UpdatePreviousPathName,
Lang,
} = useUserStore(); } = useUserStore();
const getShareCode = (url: string) => { const getShareCode = (url: string) => {
@ -51,7 +52,7 @@ function PhoneForm() {
}; };
const config = { const config = {
headers: { headers: {
"Accept-Language": navigator.language, "Accept-Language": Lang,
}, },
}; };
const sendVerificationCode = async () => { const sendVerificationCode = async () => {
@ -153,6 +154,7 @@ function PhoneForm() {
console.warn(error); console.warn(error);
} }
}; };
return ( return (
<Form <Form
name="form" name="form"
@ -177,6 +179,14 @@ function PhoneForm() {
name="account" name="account"
rules={[ rules={[
{ required: true, message: t("Please enter your phone number") }, { 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"> <div className="phone-box">

View File

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

View File

@ -19,5 +19,6 @@
"Official Website": "Official Website", "Official Website": "Official Website",
"Download": "Download", "Download": "Download",
"send successfully": "send successfully", "send successfully": "send successfully",
"Send failure":"Send failure" "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 [selectIndex, setSelectIndex] = useState<number>(0);
const { previousPathName, UpdatePreviousPathName } = useUserStore(); const { previousPathName, UpdatePreviousPathName } = useUserStore();
const navigate = useNavigate(); const navigate = useNavigate();
const { UpdateLang } = useUserStore();
const handleTabs = (num: number) => { const handleTabs = (num: number) => {
return () => { return () => {
UpdatePreviousPathName("/"); UpdatePreviousPathName("/");
@ -70,6 +71,7 @@ function SignIn() {
onClick={() => { onClick={() => {
i18n.changeLanguage("cn"); i18n.changeLanguage("cn");
setVisible(false); setVisible(false);
UpdateLang("zh-TW");
}} }}
> >
@ -80,6 +82,7 @@ function SignIn() {
onClick={() => { onClick={() => {
i18n.changeLanguage("en"); i18n.changeLanguage("en");
setVisible(false); setVisible(false);
UpdateLang("en-US");
}} }}
> >
English English

View File

@ -1,21 +1,25 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-01-19 11:31:12 * @Date: 2024-01-19 11:31:12
* @LastEditTime: 2024-01-25 15:42:25 * @LastEditTime: 2024-06-03 14:52:45
* @Author: John * @Author: John
*/ */
import { create } from "zustand"; import { create } from "zustand";
import { CountryItem } from "../type/SelectCountry"; import { CountryItem } from "../type/SelectCountry";
export type LanguageCode = "en-US" | "zh-CN" | "zh-TW" | "ko-KR";
// 状态管理器 // 状态管理器
export interface UserState { export interface UserState {
SelectCountry: CountryItem | null; SelectCountry: CountryItem | null;
UpdateSelectCountry: (item: CountryItem) => void UpdateSelectCountry: (item: CountryItem) => void;
Token: string; Token: string;
UpdateToken: (token: string) => void; UpdateToken: (token: string) => void;
CurrentPhoneNumber: string; CurrentPhoneNumber: string;
UpdateCurrentPhoneNumber: (number: string) => void; UpdateCurrentPhoneNumber: (number: string) => void;
previousPathName: string; previousPathName: string;
UpdatePreviousPathName: (number: string) => void; UpdatePreviousPathName: (number: string) => void;
Lang: LanguageCode;
UpdateLang: (lan: LanguageCode) => void;
} }
const useUserStore = create<UserState>()((set) => ({ const useUserStore = create<UserState>()((set) => ({
@ -30,16 +34,22 @@ const useUserStore = create<UserState>()((set) => ({
set((state) => { set((state) => {
return { ...state, Token: token }; return { ...state, Token: token };
}), }),
CurrentPhoneNumber:'', CurrentPhoneNumber: "",
UpdateCurrentPhoneNumber: (val) => UpdateCurrentPhoneNumber: (val) =>
set((state) => { set((state) => {
return { ...state, CurrentPhoneNumber: val }; return { ...state, CurrentPhoneNumber: val };
}), }),
previousPathName:'/', previousPathName: "/",
UpdatePreviousPathName: (url) => UpdatePreviousPathName: (url) =>
set((state) => { set((state) => {
return {...state,previousPathName:url} return { ...state, previousPathName: url };
}) }),
Lang: "en-US",
UpdateLang: (Lang) => {
set((state) => {
return { ...state, Lang };
});
},
})); }));
export default useUserStore; export default useUserStore;