Files
tongxunruanjian/pc-client/electron/preload/index.ts
T
KIMI 7ce40e356f 新增 pc-client:畅联 PC 端工程(Electron+React,按确认效果图改造,B-59)
- 基于 openim-electron-demo 改造:工号+密码登录(自研账号服务)、会话列表/聊天窗/通讯录界面重做
- 文字/语音/文件/图片消息、文件拖拽发送、表情面板、一对一语音通话(LiveKit)
- RTC 令牌对接账号服务带鉴权版 /api/rtc_token(Bearer imToken + {room,identity})
- account-service: CORS Allow-Headers 补 authorization(浏览器/渲染进程跨域调 rtc_token 需要)
- 附本地 mock 账号服务(scripts/mock-account-server.js)与截图联调脚本
2026-08-09 09:11:06 +08:00

119 lines
3.2 KiB
TypeScript

import fs from "fs";
import path from "path";
import { DataPath, IElectronAPI } from "./../../src/types/globalExpose.d";
import { contextBridge, ipcRenderer } from "electron";
import { isProd } from "../utils";
import "@openim/electron-client-sdk/lib/preload";
import { Platform } from "@openim/wasm-client-sdk";
const getPlatform = () => {
if (process.platform === "darwin") {
return Platform.MacOSX;
}
if (process.platform === "win32") {
return Platform.Windows;
}
return Platform.Linux;
};
const getDataPath = (key: DataPath) => {
switch (key) {
case "public":
return isProd ? ipcRenderer.sendSync("getDataPath", "public") : "";
case "sdkResources":
return isProd ? ipcRenderer.sendSync("getDataPath", "sdkResources") : "";
case "logsPath":
return isProd ? ipcRenderer.sendSync("getDataPath", "logsPath") : "";
default:
return "";
}
};
const subscribe = (channel: string, callback: (...args: any[]) => void) => {
const subscription = (_, ...args) => callback(...args);
ipcRenderer.on(channel, subscription);
return () => ipcRenderer.removeListener(channel, subscription);
};
const subscribeOnce = (channel: string, callback: (...args: any[]) => void) => {
ipcRenderer.once(channel, (_, ...args) => callback(...args));
};
const unsubscribeAll = (channel: string) => {
ipcRenderer.removeAllListeners(channel);
};
const ipcInvoke = (channel: string, ...arg: any) => {
return ipcRenderer.invoke(channel, ...arg);
};
const ipcSendSync = (channel: string, ...arg: any) => {
return ipcRenderer.sendSync(channel, ...arg);
};
const getUniqueSavePath = (originalPath: string) => {
let counter = 0;
let savePath = originalPath;
let fileDir = path.dirname(originalPath);
let fileName = path.basename(originalPath);
let fileExt = path.extname(originalPath);
let baseName = path.basename(fileName, fileExt);
while (fs.existsSync(savePath)) {
counter++;
fileName = `${baseName}(${counter})${fileExt}`;
savePath = path.join(fileDir, fileName);
}
return savePath;
};
const getFileByPath = async (filePath: string) => {
try {
const filename = path.basename(filePath);
const data = await fs.promises.readFile(filePath);
return new File([data], filename);
} catch (error) {
console.log(error);
return null;
}
};
const saveFileToDisk = async ({
file,
sync,
}: {
file: File;
sync?: boolean;
}): Promise<string> => {
const arrayBuffer = await file.arrayBuffer();
const saveDir = ipcRenderer.sendSync("getDataPath", "sdkResources");
const savePath = path.join(saveDir, file.name);
const uniqueSavePath = getUniqueSavePath(savePath);
if (!fs.existsSync(saveDir)) {
fs.mkdirSync(saveDir, { recursive: true });
}
if (sync) {
await fs.promises.writeFile(uniqueSavePath, Buffer.from(arrayBuffer));
} else {
fs.promises.writeFile(uniqueSavePath, Buffer.from(arrayBuffer));
}
return uniqueSavePath;
};
const Api: IElectronAPI = {
getDataPath,
getVersion: () => process.version,
getPlatform,
getSystemVersion: process.getSystemVersion,
subscribe,
subscribeOnce,
unsubscribeAll,
ipcInvoke,
ipcSendSync,
getFileByPath,
saveFileToDisk,
};
contextBridge.exposeInMainWorld("electronAPI", Api);