D: 删除通信桥接层及相关实现 (AppBridge, BaseBridge, BridgeFactory, CSharpBridge, IBridge, TauriBridge, WebMockBridge)
This commit is contained in:
1 parent
71fb7e2db1
commit
b14594ffb3
7 files changed
-385
No files matched your search
@@ -1,66 +0,0 @@
|
||||
import IBridge from "./IBridge";
|
||||
/**
|
||||
* 业务层类型定义
|
||||
*/
|
||||
export interface UserInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
email?: string;
|
||||
role: string;
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
id: string;
|
||||
title: string;
|
||||
message: string;
|
||||
type: 'info' | 'warning' | 'error' | 'success';
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
||||
|
||||
export interface LogPayload {
|
||||
level: LogLevel;
|
||||
message: string;
|
||||
context?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务功能层 - 提供更高级的通信功能
|
||||
*/
|
||||
export class AppBridge {
|
||||
private bridge: IBridge;
|
||||
|
||||
constructor() {
|
||||
this.bridge = BridgeFactory.create();
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
async getUserInfo(): Promise<UserInfo> {
|
||||
return this.bridge.send<UserInfo>('user.getInfo');
|
||||
}
|
||||
|
||||
// 监听系统通知
|
||||
onNotification(listener: (notification: Notification) => void): () => void {
|
||||
return this.bridge.on<Notification>('system.notification', listener);
|
||||
}
|
||||
|
||||
// 发送日志
|
||||
async sendLog(payload: LogPayload): Promise<void> {
|
||||
return this.bridge.send<void, LogPayload>('system.log', payload);
|
||||
}
|
||||
|
||||
// 获取系统配置
|
||||
async getConfig<T extends Record<string, unknown>>(key: string): Promise<T> {
|
||||
return this.bridge.send<T, { key: string }>('system.getConfig', { key });
|
||||
}
|
||||
|
||||
// 保存系统配置
|
||||
async saveConfig<T extends Record<string, unknown>>(key: string, value: T): Promise<void> {
|
||||
return this.bridge.send<void, { key: string; value: T }>('system.saveConfig', { key, value });
|
||||
}
|
||||
}
|
||||
|
||||
// 创建单例实例
|
||||
export const appBridge = new AppBridge();
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
* Time:2025/5/10 13:42 55
|
||||
* Name:BaseBridge.ts
|
||||
* Path:src/correspond
|
||||
* ProjectName:ClientApp
|
||||
* Author:charlatans
|
||||
*
|
||||
* Il n'ya qu'un héroïsme au monde :
|
||||
* c'est de voir le monde tel qu'il est et de l'aimer.
|
||||
*/
|
||||
|
||||
import type MessagePayload from "./IBridge"
|
||||
import { IBridge } from '@/correspond/IBridge'
|
||||
|
||||
/**
|
||||
* 平台适配层基类
|
||||
*/
|
||||
abstract class BaseBridge implements IBridge {
|
||||
protected listeners: Map<string, Set<(data: unknown) => void>> = new Map();
|
||||
|
||||
abstract send<TResponse = void, TRequest extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
data?: TRequest
|
||||
): Promise<TResponse>;
|
||||
|
||||
on<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): () => void {
|
||||
if (!this.listeners.has(channel)) {
|
||||
this.listeners.set(channel, new Set());
|
||||
}
|
||||
|
||||
// TypeScript 不允许将具体类型的函数分配给更通用的类型,因此这里需要类型转换
|
||||
const typedListener = listener as (data: unknown) => void;
|
||||
this.listeners.get(channel)!.add(typedListener);
|
||||
|
||||
return () => this.removeListener(channel, listener);
|
||||
}
|
||||
|
||||
once<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): () => void {
|
||||
// 创建一个一次性监听器
|
||||
const onceListener = ((data: TData) => {
|
||||
listener(data);
|
||||
this.removeListener(channel, onceListener);
|
||||
});
|
||||
|
||||
return this.on(channel, onceListener);
|
||||
}
|
||||
|
||||
off(channel: string): void {
|
||||
this.listeners.delete(channel);
|
||||
}
|
||||
|
||||
removeListener<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): void {
|
||||
const channelListeners = this.listeners.get(channel);
|
||||
if (channelListeners) {
|
||||
// 需要类型转换以匹配存储的监听器类型
|
||||
const typedListener = listener as (data: unknown) => void;
|
||||
channelListeners.delete(typedListener);
|
||||
if (channelListeners.size === 0) {
|
||||
this.listeners.delete(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected dispatchEvent<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
data: TData
|
||||
): void {
|
||||
const listeners = this.listeners.get(channel);
|
||||
if (listeners) {
|
||||
listeners.forEach(listener => {
|
||||
try {
|
||||
listener(data);
|
||||
} catch (error) {
|
||||
console.error(`Error in listener for channel ${channel}:`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import CSharpBridge from "./CSharpBridge";
|
||||
import TauriBridge from "./TauriBridge";
|
||||
/**
|
||||
* 桥梁工厂 - 根据运行环境创建适当的桥梁实例
|
||||
*/
|
||||
export class BridgeFactory {
|
||||
static create(): IBridge {
|
||||
if (typeof window !== 'undefined') {
|
||||
// 根据环境判断使用哪个桥接实现
|
||||
if (window.csharpApp) {
|
||||
return new CSharpBridge();
|
||||
} else if (window.__TAURI__) {
|
||||
return new TauriBridge();
|
||||
}
|
||||
}
|
||||
|
||||
// 默认返回一个Web模拟实现
|
||||
return new WebMockBridge();
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import BaseBridge from "./BaseBridge"
|
||||
/**
|
||||
* C#套壳浏览器的适配器
|
||||
*/
|
||||
class CSharpBridge extends BaseBridge {
|
||||
constructor() {
|
||||
super();
|
||||
// 假设C#注入了window.csharpApp对象
|
||||
if (typeof window !== 'undefined' && window.csharpApp) {
|
||||
// 监听C#发来的消息
|
||||
window.receiveCSharpMessage = (channel: string, dataJson: string) => {
|
||||
try {
|
||||
const data = JSON.parse(dataJson) as MessagePayload;
|
||||
this.dispatchEvent(channel, data);
|
||||
} catch (error) {
|
||||
console.error('Failed to parse message from C#:', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async send<TResponse = void, TRequest extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
data?: TRequest
|
||||
): Promise<TResponse> {
|
||||
if (typeof window === 'undefined' || !window.csharpApp) {
|
||||
throw new BridgeError('CSharp bridge not available', 'BRIDGE_UNAVAILABLE');
|
||||
}
|
||||
|
||||
try {
|
||||
// 假设C#提供了sendToCSharp方法
|
||||
const responseJson = window.csharpApp.sendToCSharp(
|
||||
channel,
|
||||
JSON.stringify(data || {})
|
||||
);
|
||||
return JSON.parse(responseJson) as TResponse;
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new BridgeError(`Failed to send message to C#: ${error.message}`, 'SEND_FAILED');
|
||||
}
|
||||
throw new BridgeError('Unknown error when sending message to C#', 'UNKNOWN_ERROR');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Time:2025/5/10 13:31 41
|
||||
* Name:IBridge.ts
|
||||
* Path:src/correspond
|
||||
* ProjectName:ClientApp
|
||||
* Author:charlatans
|
||||
*
|
||||
* Il n'ya qu'un héroïsme au monde :
|
||||
* c'est de voir le monde tel qu'il est et de l'aimer.
|
||||
*/
|
||||
/**
|
||||
* 消息类型定义 - 用于类型安全的通信
|
||||
*/
|
||||
export type MessagePayload = Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* 核心接口层 - 定义与后端通信的基本能力
|
||||
*/
|
||||
export interface IBridge {
|
||||
// 发送消息到后端
|
||||
send<TResponse = void, TRequest extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
data?: TRequest
|
||||
): Promise<TResponse>;
|
||||
|
||||
// 监听后端消息
|
||||
on<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): () => void;
|
||||
|
||||
// 只监听一次后端消息
|
||||
once<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): () => void;
|
||||
|
||||
// 移除指定通道的所有监听器
|
||||
off(channel: string): void;
|
||||
|
||||
// 移除特定监听器
|
||||
removeListener<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义Window扩展,用于与原生平台交互
|
||||
*/
|
||||
interface CSharpAppInterface {
|
||||
sendToCSharp(channel: string, dataJson: string): string;
|
||||
}
|
||||
|
||||
interface TauriInterface {
|
||||
invoke<T>(cmd: string, args?: unknown): Promise<T>;
|
||||
event: {
|
||||
listen(event: string, handler: (event: { payload: unknown }) => void): Promise<() => void>;
|
||||
once(event: string, handler: (event: { payload: unknown }) => void): Promise<void>;
|
||||
unlisten(event: string): Promise<void>;
|
||||
};
|
||||
}
|
||||
|
||||
interface WindowWithNative extends Window {
|
||||
csharpApp?: CSharpAppInterface;
|
||||
receiveCSharpMessage?: (channel: string, dataJson: string) => void;
|
||||
__TAURI__?: TauriInterface;
|
||||
}
|
||||
|
||||
declare let window: WindowWithNative;
|
||||
|
||||
/**
|
||||
* 异常类型定义
|
||||
*/
|
||||
export class BridgeError extends Error {
|
||||
constructor(message: string, public readonly code?: string) {
|
||||
super(message);
|
||||
this.name = 'BridgeError';
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import BaseBridge from "./BaseBridge";
|
||||
/**
|
||||
* Tauri适配器
|
||||
*/
|
||||
class TauriBridge extends BaseBridge {
|
||||
constructor() {
|
||||
super();
|
||||
// Tauri初始化代码
|
||||
if (typeof window !== 'undefined' && window.__TAURI__) {
|
||||
// 设置Tauri事件监听
|
||||
window.__TAURI__.event.listen('tauri://event', (event: { payload: unknown }) => {
|
||||
const eventData = event.payload as { channel: string; payload: MessagePayload };
|
||||
if (eventData.channel) {
|
||||
this.dispatchEvent(eventData.channel, eventData.payload);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async send<TResponse = void, TRequest extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
data?: TRequest
|
||||
): Promise<TResponse> {
|
||||
if (typeof window === 'undefined' || !window.__TAURI__) {
|
||||
throw new BridgeError('Tauri bridge not available', 'BRIDGE_UNAVAILABLE');
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用Tauri的invoke函数
|
||||
return await window.__TAURI__.invoke<TResponse>(channel, data || {});
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new BridgeError(`Failed to invoke Tauri command: ${error.message}`, 'INVOKE_FAILED');
|
||||
}
|
||||
throw new BridgeError('Unknown error when invoking Tauri command', 'UNKNOWN_ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
override on<TData extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
listener: (data: TData) => void
|
||||
): () => void {
|
||||
const unsubscribe = super.on(channel, listener);
|
||||
|
||||
// 向Tauri注册事件监听
|
||||
if (typeof window !== 'undefined' && window.__TAURI__) {
|
||||
window.__TAURI__.event.listen(channel, (event: { payload: unknown }) => {
|
||||
listener(event.payload as TData);
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
return unsubscribe;
|
||||
}
|
||||
|
||||
override off(channel: string): void {
|
||||
super.off(channel);
|
||||
// Tauri的事件注销需要特殊处理
|
||||
if (typeof window !== 'undefined' && window.__TAURI__) {
|
||||
window.__TAURI__.event.unlisten(channel).catch(console.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import BaseBridge from "./BaseBridge";
|
||||
/**
|
||||
* Web环境的模拟实现 - 用于开发调试
|
||||
*/
|
||||
class WebMockBridge extends BaseBridge {
|
||||
async send<TResponse = void, TRequest extends MessagePayload = MessagePayload>(
|
||||
channel: string,
|
||||
data?: TRequest
|
||||
): Promise<TResponse> {
|
||||
console.log(`[WebMock] Send to channel ${channel}:`, data);
|
||||
// 模拟异步响应
|
||||
return new Promise<TResponse>(resolve => {
|
||||
setTimeout(() => {
|
||||
// 默认的模拟响应
|
||||
const mockResponse = { success: true, mock: true } as unknown as TResponse;
|
||||
resolve(mockResponse);
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// 用于测试 - 模拟后端发送消息
|
||||
mockReceive<TData extends MessagePayload = MessagePayload>(channel: string, data: TData): void {
|
||||
this.dispatchEvent(channel, data);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user