From cc0f5e2bf54dcb41a400884e4f48a14d2ba415b4 Mon Sep 17 00:00:00 2001 From: john Date: Mon, 3 Jun 2024 18:37:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9E=20fix:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、去掉接口language参数 2、修复Accept-Language参数 3、手机号校验 4、全局语言标识 --- src/api/request.ts | 122 +++++++++++++++++++---------------- src/components/EmailForm.tsx | 4 +- src/components/PhoneForm.tsx | 12 +++- src/pages/SignIn.tsx | 3 + src/store/user.ts | 36 +++++++---- 5 files changed, 108 insertions(+), 69 deletions(-) diff --git a/src/api/request.ts b/src/api/request.ts index c124772..e6932c2 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -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 = { - language: 'zh-cn', + const customHeaders: Partial = { + // 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{ +interface axiosTypes { data: T; status: number; statusText: string; @@ -47,66 +52,75 @@ interface axiosTypes{ //后台响应数据格式 //###该接口用于规定后台返回的数据格式,意为必须携带code、msg以及result //###而result的数据格式 由外部提供。如此即可根据不同需求,定制不同的数据格式 -interface responseTypes{ - code: number, - msg: string, - result: T +interface responseTypes { + code: number; + msg: string; + result: T; } //核心处理代码 将返回一个promise 调用then将可获取响应的业务数据 -const requestHandler = (method: 'get' | 'post' | 'put' | 'delete', url: string, params: object = {}, config: AxiosRequestConfig = {}): Promise => { +const requestHandler = ( + method: "get" | "post" | "put" | "delete", + url: string, + params: object = {}, + config: AxiosRequestConfig = {} +): Promise => { let response: Promise>>; - 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((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: (url: string, params?: object, config?: AxiosRequestConfig) => requestHandler('get', url, params, config), - post: (url: string, params?: object, config?: AxiosRequestConfig) => requestHandler('post', url, params, config), - put: (url: string, params?: object, config?: AxiosRequestConfig) => requestHandler('put', url, params, config), - delete: (url: string, params?: object, config?: AxiosRequestConfig) => requestHandler('delete', url, params, config) + get: (url: string, params?: object, config?: AxiosRequestConfig) => + requestHandler("get", url, params, config), + post: (url: string, params?: object, config?: AxiosRequestConfig) => + requestHandler("post", url, params, config), + put: (url: string, params?: object, config?: AxiosRequestConfig) => + requestHandler("put", url, params, config), + delete: (url: string, params?: object, config?: AxiosRequestConfig) => + requestHandler("delete", url, params, config), }; // 导出至外层,方便统一使用 -export { request }; \ No newline at end of file +export { request }; diff --git a/src/components/EmailForm.tsx b/src/components/EmailForm.tsx index 7d61910..f7b7934 100644 --- a/src/components/EmailForm.tsx +++ b/src/components/EmailForm.tsx @@ -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(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 () => { diff --git a/src/components/PhoneForm.tsx b/src/components/PhoneForm.tsx index 4b07458..7579e3e 100644 --- a/src/components/PhoneForm.tsx +++ b/src/components/PhoneForm.tsx @@ -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 (
{ + if (v != "" && !/^\d+$/.test(v)) { + return Promise.reject(new Error("无效手机号")); + } + return Promise.resolve(); + }, + }, ]} >
diff --git a/src/pages/SignIn.tsx b/src/pages/SignIn.tsx index faac36c..9a36037 100644 --- a/src/pages/SignIn.tsx +++ b/src/pages/SignIn.tsx @@ -20,6 +20,7 @@ function SignIn() { const [selectIndex, setSelectIndex] = useState(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 diff --git a/src/store/user.ts b/src/store/user.ts index 440dd53..fc0f1dc 100644 --- a/src/store/user.ts +++ b/src/store/user.ts @@ -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()((set) => ({ @@ -30,16 +34,22 @@ const useUserStore = create()((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; From d4a96614b39e23b49d63dcbe5ab0a2bf174a3c9f Mon Sep 17 00:00:00 2001 From: john Date: Mon, 3 Jun 2024 18:42:17 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9E=20fix:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复翻译 --- src/components/PhoneForm.tsx | 2 +- src/i18n/cn/translation.json | 5 +++-- src/i18n/en/translation.json | 41 ++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/components/PhoneForm.tsx b/src/components/PhoneForm.tsx index 7579e3e..84b4292 100644 --- a/src/components/PhoneForm.tsx +++ b/src/components/PhoneForm.tsx @@ -182,7 +182,7 @@ function PhoneForm() { { validator: (_, v) => { if (v != "" && !/^\d+$/.test(v)) { - return Promise.reject(new Error("无效手机号")); + return Promise.reject(new Error(t("Invalid phone number"))); } return Promise.resolve(); }, diff --git a/src/i18n/cn/translation.json b/src/i18n/cn/translation.json index a22812d..6d02926 100644 --- a/src/i18n/cn/translation.json +++ b/src/i18n/cn/translation.json @@ -19,5 +19,6 @@ "Official Website": "官方網站", "Download": "下載", "send successfully": "發送成功", - "Send failure": "發送失敗" -} \ No newline at end of file + "Send failure": "發送失敗", + "Invalid phone number": "無效手機號碼" +} diff --git a/src/i18n/en/translation.json b/src/i18n/en/translation.json index 3e24ed8..e79f857 100644 --- a/src/i18n/en/translation.json +++ b/src/i18n/en/translation.json @@ -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" }