first commit
This commit is contained in:
48
src/hook/fetchFn.tsx
Normal file
48
src/hook/fetchFn.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { useCallback, useState } from "react";
|
||||
const useHttpClient = (baseurl:string) => {
|
||||
interface ApiError extends Error {
|
||||
status?: number;
|
||||
message: string;
|
||||
}
|
||||
const httpClient = useCallback(async (url: string, options: any = {},token:string='') => {
|
||||
try {
|
||||
const defaultOptions: any = {
|
||||
method: "GET",
|
||||
...options,
|
||||
headers: {
|
||||
...options.headers,
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
};
|
||||
if (options.body instanceof FormData) {
|
||||
delete defaultOptions.headers['content-type'];
|
||||
} else {
|
||||
defaultOptions.headers['content-type'] = 'application/json';
|
||||
}
|
||||
const response = await fetch(`${baseurl}${url}`, defaultOptions);
|
||||
const responseBody = await response.text() as any;
|
||||
if (response.status === 401) {
|
||||
const errorData: any = JSON.parse(responseBody);
|
||||
const error: ApiError = new Error(errorData.message);
|
||||
error.status = response.status;
|
||||
throw error;
|
||||
}
|
||||
if ([400, 403, 500].includes(response.status)) {
|
||||
const errorData: any = JSON.parse(responseBody);
|
||||
const error = new Error(errorData.message);
|
||||
(error as any).status = response.status;
|
||||
throw error;
|
||||
}
|
||||
return JSON.parse(responseBody);
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error) || !(error as any).status) {
|
||||
console.error("Request failed:", error);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { httpClient };
|
||||
};
|
||||
|
||||
export default useHttpClient;
|
||||
29
src/hook/i18n.ts
Normal file
29
src/hook/i18n.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import i18next from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import { translations } from '../locales/translations';
|
||||
import { storage } from './useStore';
|
||||
const i18n = i18next;
|
||||
i18n.use(initReactI18next).init({
|
||||
lng: "en",
|
||||
fallbackLng: "tw",
|
||||
debug: false,
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
},
|
||||
resources: {
|
||||
'zh-CN': { translation: translations['zh-CN'] },
|
||||
'zh-TW': { translation: translations['zh-TW'] },
|
||||
'en': { translation: translations['en'] },
|
||||
'ja': { translation: translations['ja'] },
|
||||
'ko': { translation: translations['ko'] }
|
||||
},
|
||||
})
|
||||
|
||||
storage.get('language').then((res:any)=>{
|
||||
if(res){
|
||||
i18n.changeLanguage(res)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
export default i18n;
|
||||
62
src/hook/supabase.ts
Normal file
62
src/hook/supabase.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { createClient, SupabaseClient } from "@supabase/supabase-js";
|
||||
import { storage } from "./useStore";
|
||||
import { onlyStandalone } from '../utils/getbaseurl'
|
||||
|
||||
// 定义环境变量的默认值
|
||||
const SUPABASE_URL = process.env.REACT_SUPABASE_URL || '';
|
||||
const SUPABASE_ANON_KEY = process.env.REACT_SUPABASE_ANON_KEY || '';
|
||||
|
||||
let supabase: any = null;
|
||||
export const getSupabaseClient = (): SupabaseClient => {
|
||||
if (!supabase&&!onlyStandalone) {
|
||||
supabase = createClient(
|
||||
SUPABASE_URL,
|
||||
SUPABASE_ANON_KEY,
|
||||
{
|
||||
db: { schema: "limq" },
|
||||
auth: {
|
||||
storage: storageAdapter,
|
||||
persistSession: true,
|
||||
autoRefreshToken: true,
|
||||
},
|
||||
realtime: {
|
||||
params: {
|
||||
eventsPerSecond: 10,
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return supabase;
|
||||
};
|
||||
|
||||
const storageAdapter = {
|
||||
getItem: async (key: string) => {
|
||||
try {
|
||||
const result: any = await storage.get(key);
|
||||
return result || null;
|
||||
} catch (error) {
|
||||
console.error("Storage get error:", error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
setItem: async (key: string, value: string) => {
|
||||
try {
|
||||
await storage.set(key, value);
|
||||
} catch (error) {
|
||||
console.error("Storage set error:", error);
|
||||
}
|
||||
},
|
||||
|
||||
removeItem: async (key: string) => {
|
||||
try {
|
||||
await storage.remove(key);
|
||||
} catch (error) {
|
||||
console.error("Storage remove error:", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
export const clearSupabaseInstance = () => {
|
||||
supabase = null;
|
||||
};
|
||||
60
src/hook/useFile.tsx
Normal file
60
src/hook/useFile.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { message } from 'antd';
|
||||
|
||||
export const useUpload = (supabaseClient: any) => {
|
||||
const upload = async (file: any, bucket: string, name: string) => {
|
||||
if (!file) return;
|
||||
|
||||
try {
|
||||
const timestamp = Date.now();
|
||||
|
||||
// 处理文件名
|
||||
const cleanFileName = name?.replace(/[^a-zA-Z0-9.-]/g, '_'); // 清理特殊字符
|
||||
|
||||
// 确保文件名不为空且包含扩展名
|
||||
const fileExtension = file.type === 'application/pdf' ? '.pdf' :
|
||||
file.type === 'image/gif' ? '.gif' :
|
||||
'.file'; // 默认扩展名
|
||||
|
||||
// 组合最终的文件名
|
||||
const uniqueFileName = cleanFileName
|
||||
? `${timestamp}_${cleanFileName}${cleanFileName.includes('.') ? '' : fileExtension}`
|
||||
: `${timestamp}${fileExtension}`;
|
||||
|
||||
const { data, error } = await supabaseClient
|
||||
.storage
|
||||
.from(bucket)
|
||||
.upload(uniqueFileName, file, {
|
||||
cacheControl: '3600',
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
|
||||
message.success('文件上传成功');
|
||||
return data?.path;
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
return { upload };
|
||||
};
|
||||
|
||||
export const useGetPublicUrl = (supabaseClient:any) => {
|
||||
const getPublicUrl = async (filePath: string, bucket: string) => {
|
||||
const { data: urlData, error: urlError } = supabaseClient
|
||||
.storage
|
||||
.from(bucket) // 指定存储桶名称
|
||||
.getPublicUrl(filePath);
|
||||
|
||||
if (urlError) {
|
||||
message.error(`获取公共 URL 失败: ${urlError.message}`);
|
||||
return null; // 如果获取失败,返回 null
|
||||
} else {
|
||||
return urlData?.publicUrl; // 成功时返回公共 URL
|
||||
}
|
||||
};
|
||||
|
||||
return { getPublicUrl };
|
||||
};
|
||||
85
src/hook/useStore.tsx
Normal file
85
src/hook/useStore.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
interface StorageMessage {
|
||||
type: "setStorage" | "getStorage" | "removeStorage";
|
||||
key: string;
|
||||
value?: any;
|
||||
}
|
||||
|
||||
// 统一的发送消息函数
|
||||
const sendMessageToFigma = (type: string, data?: any) => {
|
||||
parent.postMessage({ pluginMessage: { type, ...data } }, '*');
|
||||
};
|
||||
|
||||
export const storage = {
|
||||
set: async (key: string, value: any) => {
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
const messageHandler = (event: MessageEvent) => {
|
||||
const msg = event.data.pluginMessage;
|
||||
if (msg?.type === 'storageSet') {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
if (msg.success) {
|
||||
resolve(true);
|
||||
} else {
|
||||
reject(msg.error);
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', messageHandler);
|
||||
|
||||
// 发送设置存储的消息
|
||||
sendMessageToFigma('setStorage', { key, value });
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error, '222222');
|
||||
}
|
||||
},
|
||||
|
||||
get: async (key: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const messageHandler = (event: MessageEvent) => {
|
||||
const msg = event.data.pluginMessage;
|
||||
if (msg?.type === 'storageGet') {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
if (msg.value !== undefined) {
|
||||
resolve(msg.value);
|
||||
} else {
|
||||
reject(msg.error);
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', messageHandler);
|
||||
|
||||
// 发送获取存储的消息
|
||||
sendMessageToFigma('getStorage', { key });
|
||||
} catch (error) {
|
||||
reject(null);
|
||||
console.log(error, 'getgetgetget4444');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
remove: async (key: string) => {
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
const messageHandler = (event: MessageEvent) => {
|
||||
const msg = event.data.pluginMessage;
|
||||
if (msg?.type === 'storageRemoved') {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
if (msg.success) {
|
||||
resolve(true);
|
||||
} else {
|
||||
reject(msg.error);
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', messageHandler);
|
||||
|
||||
// 发送删除存储的消息
|
||||
sendMessageToFigma('removeStorage', { key });
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to remove storage:', error);
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user