Initial clean project import

This commit is contained in:
cat-shark
2026-06-19 18:41:41 +08:00
commit a13b804c7a
1306 changed files with 220568 additions and 0 deletions
+287
View File
@@ -0,0 +1,287 @@
import {ipcMain, shell} from "electron";
import {AppConfig} from "../../../src/config";
import {ResultType} from "../../lib/api";
import {Events} from "../event/main";
import {platformUUID} from "../../lib/env";
import {AppsMain} from "../app/main";
import Apps from "../app";
import StorageMain from "../storage/main";
import {Log} from "../log/main";
const init = async () => {
// 用户功能未启用,跳过自动刷新
console.log('[User.init] 跳过用户信息自动刷新(userEnable=false');
Log.info('User.init', '跳过用户信息自动刷新(userEnable=false');
return null;
// 注释:原来的代码会调用 refresh() API,但用户功能未启用,所以永久禁用
// setTimeout(() => {
// refresh().then();
// }, 1000);
};
const userData = {
isInit: false,
apiToken: "",
user: {
id: "",
name: "",
avatar: "",
deviceCode: "",
},
data: {},
basic: {},
};
const get = async (): Promise<{
apiToken: string;
user: {
id: string;
name: string;
avatar: string;
deviceCode: string;
};
data: {
[key: string]: any;
};
basic: {
[key: string]: any;
};
}> => {
if (!userData.isInit) {
const userStorageData = await StorageMain.get("user", "data", {});
userData.apiToken = userStorageData.apiToken || "";
userData.user = userStorageData.user || {};
userData.data = userStorageData.data || {};
userData.basic = userStorageData.basic || {};
userData.isInit = true;
}
userData.user.id = userData.user.id || "";
return {
apiToken: userData.apiToken,
user: userData.user,
data: userData.data,
basic: userData.basic,
};
};
ipcMain.handle(
"user:open",
async (
event,
option?: {
readyParam: {
page?: string;
[key: string]: any;
};
}
) => {
option = Object.assign(
{
readyParam: null,
},
option || {}
);
await AppsMain.windowOpen("user", option);
if (option.readyParam) {
await Events.callPage("user", "ready", option.readyParam);
}
}
);
ipcMain.handle("user:get", async event => {
return get();
});
const save = async (data: {apiToken: string; user: any; data: any; basic: {}}) => {
userData.apiToken = data.apiToken || "";
userData.user = data.user || {};
userData.data = data.data || {};
userData.user.id = userData.user.id || "";
Events.broadcast("UserChange", {});
await StorageMain.set("user", "data", {
apiToken: data.apiToken,
user: data.user,
data: data.data,
basic: data.basic,
});
};
ipcMain.handle("user:save", async (event, data) => {
return save(data);
});
const refresh = async () => {
const result = await userInfoApi();
// console.log("user.refresh", JSON.stringify(result, null, 2));
await save({
apiToken: result.data.apiToken,
user: result.data.user,
data: result.data.data,
basic: result.data.basic,
});
};
ipcMain.handle("user:refresh", async event => {
return refresh();
});
const getApiToken = async (): Promise<string> => {
await get();
return userData.apiToken;
};
ipcMain.handle("user:getApiToken", async event => {
return getApiToken();
});
const getWebEnterUrl = async (url: string) => {
let param = [];
const apiToken = await getApiToken();
if (apiToken) {
param.push(`api_token=${apiToken}`);
}
if (await AppsMain.shouldDarkMode()) {
param.push(`is_dark=1`);
}
param.push(`device_uuid=${platformUUID()}`);
param.push(`url=${encodeURIComponent(url)}`);
return `${AppConfig.apiBaseUrl}/app_manager/enter?${param.join("&")}`;
};
ipcMain.handle("user:getWebEnterUrl", async (event, url) => {
return getWebEnterUrl(url);
});
const openWebUrl = async (url: string) => {
url = await getWebEnterUrl(url);
await shell.openExternal(url);
};
ipcMain.handle("user:openWebUrl", async (event, url) => {
return openWebUrl(url);
});
const apiPost = async (
url: string,
data: Record<string, any>,
option?: {
throwException?: boolean;
}
) => {
return post(url, data, option);
};
ipcMain.handle("user:apiPost", async (event, url, data, option) => {
return apiPost(url, data, option);
});
export const User = {
init,
get,
save,
getApiToken,
getWebEnterUrl,
openWebUrl,
};
export default User;
const post = async <T>(
api: string,
data: Record<string, any>,
option?: {
throwException?: boolean;
retry?: number;
retryTimes?: number;
retryInterval?: number;
}
): Promise<ResultType<T>> => {
option = Object.assign(
{
throwException: true,
retry: 0,
retryTimes: 0,
retryInterval: 5,
},
option
);
let url = api;
if (!api.startsWith("http:") && !api.startsWith("https:")) {
url = `${AppConfig.apiBaseUrl}/${api}`;
}
const apiToken = await User.getApiToken();
let json = null,
res = null;
try {
res = await fetch(url, {
method: "POST",
headers: {
"User-Agent": Apps.getUserAgent(),
"Content-Type": "application/json",
"Api-Token": apiToken,
},
body: JSON.stringify(data),
});
if (res.status !== 200) {
if (option.retry > 0 && option.retryTimes < option.retry) {
option.retryTimes++;
Log.info("user.post.retry", {api, data, res, retryTimes: option.retryTimes});
await new Promise(resolve => setTimeout(resolve, option.retryInterval * 1000));
return await post(api, data, option);
}
Log.error("user.post.error", {api, data, res});
if (option.throwException) {
throw `RequestError(code:${res.status},text:${res.statusText})`;
}
return {
code: 10000,
msg: `RequestError(code:${res.status},text:${res.statusText})`,
} as ResultType<T>;
}
json = await res.json();
} catch (e) {
res = `RequestError(${e})`;
}
// console.log('post', JSON.stringify({api, data, json}, null, 2))
if (!json || !("code" in json)) {
if (option.retry > 0 && option.retryTimes < option.retry) {
option.retryTimes++;
Log.info("user.post.retry", {api, data, res, retryTimes: option.retryTimes});
await new Promise(resolve => setTimeout(resolve, option.retryInterval * 1000));
return await post(api, data, option);
}
Log.error("user.post.error", {api, data, res});
if (option.throwException) {
throw "ResponseError";
}
return {code: 10000, msg: "ResponseError"};
}
if (json.code) {
// login required
if (json.code === 1001) {
if (userData.user && userData.user.id) {
await refresh();
}
}
if (option.throwException) {
throw json.msg;
}
}
return json;
};
const userInfoApi = async (): Promise<
ResultType<{
apiToken: string;
user: object;
data: any;
basic: object;
}>
> => {
return await post("app_manager/user_info", {});
};
export const UserApi = {
post,
userInfoApi,
};
+45
View File
@@ -0,0 +1,45 @@
import { ipcRenderer } from "electron";
const open = async (option: any) => {
return ipcRenderer.invoke("user:open", option);
};
const get = async (): Promise<any> => {
return ipcRenderer.invoke("user:get");
};
const refresh = async () => {
return ipcRenderer.invoke("user:refresh");
};
const getApiToken = async (): Promise<string> => {
return ipcRenderer.invoke("user:getApiToken");
};
const getWebEnterUrl = async (url: string) => {
return ipcRenderer.invoke("user:getWebEnterUrl", url);
};
const openWebUrl = async (url: string) => {
return ipcRenderer.invoke("user:openWebUrl", url);
};
const apiPost = async (
url: string,
data: Record<string, any>,
option?: {
throwException?: boolean;
}
) => {
return ipcRenderer.invoke("user:apiPost", url, data, option);
};
export default {
open,
get,
refresh,
getApiToken,
getWebEnterUrl,
openWebUrl,
apiPost,
};