288 lines
7.5 KiB
TypeScript
288 lines
7.5 KiB
TypeScript
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,
|
||
};
|