From a98f6b39683bf8603146901bc480708e30f533a6 Mon Sep 17 00:00:00 2001 From: cnwhy Date: Thu, 20 Jun 2024 18:17:44 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9F=90=E4=BA=9B=E6=83=85=E5=86=B5?= =?UTF-8?q?=E4=B8=8Bstorage=E6=95=B0=E6=8D=AE=E4=B8=8D=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=EF=BC=9B=E7=AE=80=E5=8C=96=E9=AA=8C=E8=AF=81=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 27 ++++--- src/Pages/Manage.tsx | 53 ++++++------- src/components/List/Public.tsx | 4 +- src/components/ListCard/index.tsx | 12 +-- src/uitls/ctx.tsx | 2 +- src/uitls/require.ts | 1 - src/uitls/server.ts | 121 ++++++++++++++++++------------ src/uitls/storage.ts | 21 ++++++ src/uitls/useMonacoEdit.tsx | 27 +------ 9 files changed, 142 insertions(+), 126 deletions(-) create mode 100644 src/uitls/storage.ts diff --git a/src/App.tsx b/src/App.tsx index 2bf72da..ab50c4a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,9 +6,9 @@ import React, { useLayoutEffect, useContext, } from "react"; -import { ConfigProvider, message, theme, App as AntdApp } from "antd"; +import { ConfigProvider, message, theme, App as AntdApp, Spin } from "antd"; import { - init, + userInit, logout, useInfo, useServerConfig, @@ -24,7 +24,7 @@ import enGB from "antd/locale/en_GB"; import { ServerComm } from "./api/local"; import Ctx from "./uitls/ctx"; import { useIsDark } from "./uitls/useTheme"; -import './uitls/i18n.ts'; +import "./uitls/i18n.ts"; import { useTranslation } from "react-i18next"; const Manage = React.lazy(() => import("./Pages/Manage")); @@ -36,9 +36,7 @@ const AntdGlobal: React.FC<{ children: React.ReactNode }> = (props) => { ConfigProvider.config({ theme: theme, holderRender: (children) => ( - - {children} - + {children} ), }); }, [locale, theme]); @@ -55,6 +53,7 @@ function App() { const localConfig = useLocalConfig(); const isDark = useIsDark(); // const [userTheme, setUserTheme] = useState(null); // 用户主题 + const [isInit, setIsInit] = useState(false); const [serverLoading, setServerLoading] = useState(false); const [localLoading, setLocalLoading] = useState(false); const [locale, setLocale] = useState(zhCN); @@ -102,9 +101,9 @@ function App() { }); useEffect(() => { - init(); - const apiUpdate = async (reqConfig: any) => { - if (reqConfig?.url === API.apis.config) return; + userInit().then(() => setIsInit(true)); + const apiUpdate = async () => { + // if (reqConfig?.url === API.apis.config) return; return useServerConfig.set((await API.getConfig()) as any); }; const localUpdate = async () => { @@ -143,11 +142,11 @@ function App() { (window as any)?.monaco?.editor.setTheme("vs"); } }, [isDark]); - + useEffect(() => { const lang = i18n.resolvedLanguage; - setLocale(lang === 'zh' ? zhCN : enGB); - },[i18n.resolvedLanguage]) + setLocale(lang === "zh" ? zhCN : enGB); + }, [i18n.resolvedLanguage]); return ( - - {info ? : } + }> + {isInit ? info ? : : } diff --git a/src/Pages/Manage.tsx b/src/Pages/Manage.tsx index c8b7c24..459765a 100644 --- a/src/Pages/Manage.tsx +++ b/src/Pages/Manage.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useContext, useEffect, useMemo, useRef, useState } from "react"; import { Button, Col, @@ -38,6 +38,7 @@ import { import { ThemeButton } from "../components/Theme"; import { LanguageButton } from "../components/Language"; import { useTranslation } from "react-i18next"; +import Ctx from "../uitls/ctx"; const colSpan = { xs: 24, @@ -53,6 +54,7 @@ const colSpan1 = { }; const Manage = () => { + const { isLoading } = useContext(Ctx); const info = useInfo()!; const { t } = useTranslation(); const gostConfig = useServerConfig(); @@ -62,8 +64,8 @@ const Manage = () => { const [locals, setLocals] = useState([]); const ref = useRef({}); - const updateList = useCallback(async () => { - return getLocalServers() + useEffect(() => { + getLocalServers() .then((local) => { return local.sort((a, b) => { const t1 = a.time || 0; @@ -74,24 +76,21 @@ const Manage = () => { .then((list) => setLocals( list - .filter((item) => { - if (item.addr === info.addr) return false; - return true; - }) + // .filter((item) => { + // if (item.addr === info.addr) return false; + // return true; + // }) .map((item) => ({ key: item.addr, label: {item.addr}, - // onClick: () => { - // window.open(`./?use=${item.addr}`, undefined, "noopener"); - // }, })) ) ); - }, []); + }, [info.addr]); useEffect(() => { fixOldCacheConfig().then((up) => { - up && configEvent.emit("update"); + up && configEvent.emit("update", false); }); const onSave = (ref.current.onSave = async () => { @@ -105,24 +104,16 @@ const Manage = () => { } }); - const update = () => { - setIsSaved(false); - if (!useInfo.get()?.autoSave) return; - return onSave(); - }; - - const onApiUpdate = async (reqConfig: any) => { - setIsSaved(false); - if (!useInfo.get()?.autoSave) return; - if (reqConfig?.url === API.apis.config) return; + const onAutoSave = (autoSave = false) => { + if (autoSave) setIsSaved(false); + if (!useInfo.get()?.autoSave || !autoSave) return; return onSave(); }; - updateList(); - configEvent.on("update", update); - configEvent.on("apiUpdate", onApiUpdate); + configEvent.on("update", onAutoSave); + configEvent.on("apiUpdate", onAutoSave); return () => { - configEvent.off("update", update); - configEvent.off("apiUpdate", onApiUpdate); + configEvent.off("update", onAutoSave); + configEvent.off("apiUpdate", onAutoSave); }; }, []); @@ -160,9 +151,10 @@ const Manage = () => { - + {t("manage.cmd.logout")} diff --git a/src/components/List/Public.tsx b/src/components/List/Public.tsx index 1690a07..fbf0042 100644 --- a/src/components/List/Public.tsx +++ b/src/components/List/Public.tsx @@ -71,7 +71,7 @@ const PublicList: React.FC = (props) => { const { deleteValue, updateValue, - dispatch, + disable, enable, updateLocal, deleteLocal, @@ -195,7 +195,7 @@ const PublicList: React.FC = (props) => { type="link" size={"small"} onClick={async () => { - await dispatch(record); + await disable(record); }} > {/* 禁用 */} diff --git a/src/components/ListCard/index.tsx b/src/components/ListCard/index.tsx index a94ea05..a56bbcc 100644 --- a/src/components/ListCard/index.tsx +++ b/src/components/ListCard/index.tsx @@ -88,11 +88,11 @@ const ListCard: React.FC = (props) => { return { updateValue: async (id: string, value: any, update = true) => { await api.put(id, value); - update && configEvent.emit("apiUpdate", {}); + update && configEvent.emit("apiUpdate", true); }, deleteValue: async (value: any, update = true) => { await api.delete(value.name); - update && configEvent.emit("apiUpdate", {}); + update && configEvent.emit("apiUpdate", true); }, addValue: async (json: any, update = true) => { let addName = json.name || `${name}-0`; @@ -124,20 +124,20 @@ const ListCard: React.FC = (props) => { description: t("msg.fixName", { name: addName }), message: t("msg.autofix"), }); - update && configEvent.emit("apiUpdate", {}); + update && configEvent.emit("apiUpdate", true); }, - dispatch: async (value: any) => { + disable: async (value: any) => { if (!localApi) return; await api.delete(value.name); await localApi.add(value); - configEvent.emit("update"); + configEvent.emit("update", true); // updateLocalList?.(); }, enable: async (value: any) => { if (!localApi) return; await api.post(value); await localApi.delete(value.name); - configEvent.emit("update"); + configEvent.emit("update", true); // updateLocalList?.(); }, updateLocal: async (key: string, value: any) => { diff --git a/src/uitls/ctx.tsx b/src/uitls/ctx.tsx index 91ff838..36ca649 100644 --- a/src/uitls/ctx.tsx +++ b/src/uitls/ctx.tsx @@ -13,7 +13,7 @@ export type Comm = { updateValue: (id: string, value: any) => Promise; deleteValue: (value: any) => Promise; addValue: (json: any) => Promise; - dispatch: (value: any) => Promise; + disable: (value: any) => Promise; enable: (value: any) => Promise; updateLocal: (key: string, value: any) => Promise; deleteLocal: (value: any) => Promise; diff --git a/src/uitls/require.ts b/src/uitls/require.ts index 5d4a3ca..fd8c2f4 100644 --- a/src/uitls/require.ts +++ b/src/uitls/require.ts @@ -14,7 +14,6 @@ require.interceptors.request.use((config) => { require.interceptors.response.use( (res) => { if (res.config.method !== "get" && !(res.config as any)?.noMsg) { - // configEvent.emit("apiUpdate", res.config); message.success(t("msg.success")); } if (res.data) { diff --git a/src/uitls/server.ts b/src/uitls/server.ts index 4e66a80..13563e5 100644 --- a/src/uitls/server.ts +++ b/src/uitls/server.ts @@ -5,6 +5,8 @@ import { message } from "antd"; import { t } from "i18next"; import { ServerComm } from "../api/local"; import { Config } from "../api/types"; +import { getJsonAtLocalStorage, getJsonAtSessionStorage, setJsonAtLocalStorage, setJsonAtSessionStorage } from "./storage"; + const gostServerKey = "__GOST_SERVER__"; const uselocalServerKey = "__USE_SERVER__"; const settingKey = "__SETTINGS__"; @@ -24,68 +26,88 @@ export type GostApiConfig = { }; export type Settings = { - theme?: "dark" | "light" | 'system'; + theme?: "dark" | "light" | "system"; }; -export const useInfo = getUseValue(); -Object.defineProperty(window, gostServerKey, { - get: useInfo.get, - set: useInfo.set, -}); +const query = qs.parse(location.search, { ignoreQueryPrefix: true }); +if(query.use) { + setJsonAtSessionStorage(gostServerKey, null); + window[uselocalServerKey] = query.use; +} + +let _useInfo: GostApiConfig | null = getJsonAtSessionStorage(gostServerKey); // 冗余_useInfo +export const useInfo = getUseValue( + function get() { + return _useInfo; + }, + function set(val) { + _useInfo = val; + setJsonAtSessionStorage(gostServerKey, val); + } +); + +// Object.defineProperty(window, gostServerKey, { +// get: useInfo.get, +// set: useInfo.set, +// }); + export const useServerConfig = getUseValue | null>(); export const useLocalConfig = getUseValue | null>(); export const useSettings = getUseValue( - () => { - const json = localStorage.getItem(settingKey) || "{}"; - try { - return JSON.parse(json); - } catch (e) { - console.error(e); - return {}; - } - }, - (v) => { - if (v == null) { - localStorage.removeItem(settingKey); - } - localStorage.setItem(settingKey, JSON.stringify(v)); - } + getJsonAtLocalStorage.bind(null, settingKey, {}), + setJsonAtLocalStorage.bind(null, settingKey) ); export const getInfo = (): GostApiConfig | null => useInfo.get(); -export const init = async () => { - // 内存 - if (window[gostServerKey]) return true; +export const userInit = async () => { + // debugger; - // 本地保存 - const query = qs.parse(location.search, { ignoreQueryPrefix: true }); + // 本地保存 (切换本地保存的服务) if (query.use) { - window[uselocalServerKey] = query.use; - window.history.replaceState(null, "", location.pathname); - logout(); // 清理sessionStorage - } - - // 刷新(会话保持) - const serverJson = sessionStorage.getItem(gostServerKey); - if (serverJson) { - const server = JSON.parse(serverJson); - await login(server); - return true; - } - - // 本地保存的服务器信息 - if (window[uselocalServerKey]) { - const server = await getLocal(window[uselocalServerKey]); + const use = query.use as string; + window.history.replaceState(null, "", location.pathname); // 清理url的参数 + const server = await getLocal(use); if (server) { server.isLocal = true; await login(server); - if (server) { - server.time = Date.now(); - saveLocal(window[uselocalServerKey], server); - } + server.time = Date.now(); + saveLocal(use, server); + return; + }else{ + logout(); } } + + // 刷新页面 + const _useInfo = getInfo(); + if (_useInfo) { + await verify(_useInfo); + return; + } + + + + // 刷新(会话保持) + // const serverJson = sessionStorage.getItem(gostServerKey); + // if (serverJson) { + // const server = JSON.parse(serverJson); + // await login(server); + // return true; + // } + + // 本地保存的服务器信息 + // if (window[uselocalServerKey]) { + // const server = await getLocal(window[uselocalServerKey]); + // if (server) { + // server.isLocal = true; + // await login(server); + // if (server) { + // server.time = Date.now(); + // saveLocal(window[uselocalServerKey], server); + // } + // } + // } }; const verify = async (arg: GostApiConfig) => { @@ -102,12 +124,12 @@ const verify = async (arg: GostApiConfig) => { export const login = async (arg: GostApiConfig, save?: false) => { try { await verify(arg); - window[gostServerKey] = arg; - window.sessionStorage.setItem(gostServerKey, JSON.stringify(arg)); if (save) { arg.isLocal = true; - window[gostServerKey] = arg; + useInfo.set(arg); await saveLocal(arg.addr, arg); + }else{ + useInfo.set(arg); } } catch (e: any) { if (e === "verify error") { @@ -120,7 +142,6 @@ export const login = async (arg: GostApiConfig, save?: false) => { export const logout = async () => { useInfo.set(null); - window.sessionStorage.removeItem(gostServerKey); }; export const saveLocal = async (id: string, arg: GostApiConfig) => { diff --git a/src/uitls/storage.ts b/src/uitls/storage.ts new file mode 100644 index 0000000..bea301d --- /dev/null +++ b/src/uitls/storage.ts @@ -0,0 +1,21 @@ +function getJson(storage: Storage, key: string, defaultValue: any = null) { + const json = storage.getItem(key); + if(json == null) return defaultValue; + try { + return JSON.parse(json); + } catch (error) { + console.error(error); + return defaultValue; + } +} + +function setJson(storage: Storage, key: string, value: any) { + if (value == null) { + return storage.removeItem(key); + } + storage.setItem(key, JSON.stringify(value)); +} +export const getJsonAtSessionStorage = getJson.bind(null, sessionStorage); +export const setJsonAtSessionStorage = setJson.bind(null, sessionStorage); +export const getJsonAtLocalStorage = getJson.bind(null, localStorage); +export const setJsonAtLocalStorage = setJson.bind(null, localStorage); diff --git a/src/uitls/useMonacoEdit.tsx b/src/uitls/useMonacoEdit.tsx index 973bdbf..4f9470f 100644 --- a/src/uitls/useMonacoEdit.tsx +++ b/src/uitls/useMonacoEdit.tsx @@ -8,31 +8,12 @@ import { getI18n, useTranslation } from 'react-i18next'; (function () { const require = (window as any).require; - // let monacoURL; - // const MONACO_URL = import.meta.env.VITE_MONACO_URL || '/monaco-editor'; - // if(/^(http[s]:)?\/\//.test(MONACO_URL)){ - // monacoURL = MONACO_URL + '/min/vs' - // }else{ - // const baseURL = new URL(import.meta.env.BASE_URL, location.href).href; - // monacoURL = new URL(`${MONACO_URL}/min/vs`, baseURL).href; - // } - - // if(import.meta.env.PROD && import.meta.env.VITE_MONACO_URL){ - // monacoURL = import.meta.env.VITE_MONACO_URL + '/min/vs'; - // }else{ - // const baseURL = new URL(import.meta.env.BASE_URL, location.href).href; - // monacoURL = new URL("./monaco-editor/min/vs", baseURL).href; - // } - - // console.log(`import_meta_env_BASE_URL`, import.meta.env.BASE_URL); - // console.log("baseURL", baseURL); - // const monacoURL = `//unpkg.com/monaco-editor@0.47.0/min/vs` - // require.config({ paths: { vs: `${monacoURL}` } }); if (require) { const i18n = getI18n(); - i18n.on('languageChanged',(event)=>{ - console.log('languageChanged', event) - }) + // DOTO: monaco 动态设置语言未实现 + // i18n.on('languageChanged',(event)=>{ + // console.log('languageChanged', event) + // }) require.config({ "vs/nls": { availableLanguages: {