From 89ee08789dcb8d6293c6af4be2b114a3d337859b Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 18 May 2025 12:56:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0/api/Menu/GetConfig=3FconfigN?= =?UTF-8?q?ame=3DHelperDescrip=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=A0=B9?= =?UTF-8?q?=E6=8D=AEHTTP=E7=8A=B6=E6=80=81=E7=A0=81=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E5=B8=AE=E5=8A=A9=E6=8F=8F=E8=BF=B0=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EIAC_Desktop_Api.ts | 436 +++++++++++++++++++++------------------- src/IpcMainHandler.ts | 99 +++++++-- src/index.ts | 7 +- src/preload.ts | 7 +- src/types/electron.d.ts | 7 +- 5 files changed, 323 insertions(+), 233 deletions(-) diff --git a/src/EIAC_Desktop_Api.ts b/src/EIAC_Desktop_Api.ts index fa6d92f..3501f87 100644 --- a/src/EIAC_Desktop_Api.ts +++ b/src/EIAC_Desktop_Api.ts @@ -5,275 +5,307 @@ const EIAC_DESKTOP_API_HOST = process.env.EIAC_DESKTOP_API_HOST || 'http://1.12. * EIAC 桌面 API */ export class EIAC_Desktop_Api { - private host: string; - /** - * 构造函数,传入API Host - */ - constructor(host = EIAC_DESKTOP_API_HOST) { - this.host = host; - } + private host: string; + /** + * 构造函数,传入API Host + */ + constructor(host = EIAC_DESKTOP_API_HOST) { + this.host = host; + } + /** + * 认证接口 + */ + public Auth = { /** - * 认证接口 + * 登录 /api/Auth/Login + * @param request 登录请求 + * @param init 请求初始化,可选。 + * @returns 登录结果 */ - public Auth = { - /** - * 登录 /api/Auth/Login - * @param request 登录请求 - * @param init 请求初始化,可选。 - * @returns 登录结果 - */ - LoginAsync: async (request: LoginRequest, init?: RequestInit) => { - const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Auth/Login`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json; charset=utf-8' - }, - body: JSON.stringify(request), - ...init - }); - - return await response.json() as ApiResponse; - } - }; - - /** - * 菜单接口 - */ - public Menu = { - /** - * 获取菜单 /api/Menu/GetMenu - * @param init 请求初始化,可选。 - * @returns 菜单列表 - */ - GetMenuAsync: async (init?: RequestInit) => { - const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Menu/GetMenu`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json; charset=utf-8' - }, - ...init - }); - return await response.json() as ApiResponse; + LoginAsync: async (request: LoginRequest, init?: RequestInit): Promise> => { + const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Auth/Login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json; charset=utf-8' }, - /** - * 获取配置 /api/Menu/GetConfig - * @param configName 配置名称,可选。 - * @param init 请求初始化,可选。 - * @returns 配置列表 - */ - GetConfigAsync: async (configName = 'TagResolution', init?: RequestInit) => { - const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Menu/GetConfig?configName=${configName}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json; charset=utf-8' - }, - ...init - }); + body: JSON.stringify(request), + ...init + }); - return await response.json() as ApiResponse; - } - }; + return await response.json() as ApiResponse; + } + }; + + /** + * 菜单接口 + */ + public Menu = { + /** + * 获取菜单 /api/Menu/GetMenu + * @param init 请求初始化,可选。 + * @returns 菜单列表 + */ + GetMenuAsync: async (init?: RequestInit): Promise> => { + const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Menu/GetMenu`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + ...init + }); + return await response.json() as ApiResponse; + }, + /** + * 获取配置 /api/Menu/GetConfig + * @param configName 配置名称,可选。 + * @param init 请求初始化,可选。 + * @returns 配置列表 + */ + GetConfigAsync: async (configName: string, init?: RequestInit): Promise> => { + const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Menu/GetConfig?configName=${configName}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + ...init + }); + + return await response.json() as ApiResponse; + }, /** - * 帮助接口 + * 获取分辨率配置 /api/Menu/GetConfig?configName=TagResolution + * @param init 请求初始化,可选。 + * @returns 分辨率配置列表 */ - public Help = { - /** - * 故障报告 /api/Help/FaultReporting - * @param request 故障报告请求 - * @param init 请求初始化,可选。 - * @returns 故障报告结果 - */ - FaultReportingAsync: async (request: FaultReportingRequest, init?: RequestInit) => { - const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Help/FaultReporting`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json; charset=utf-8' - }, - body: JSON.stringify(request), - ...init - }); + GetTagResolutionsAsync: (init?: RequestInit): Promise> => { + return this.Menu.GetConfigAsync('TagResolution', init); + }, - return await response.json() as ApiResponse; - } - }; + /** + * 获取帮助描述 /api/Menu/GetConfig?configName=HelperDescrip + * @param init 请求初始化,可选。 + * @returns 帮助描述列表 + */ + GetHelperDescripsAsync: (init?: RequestInit): Promise> => { + return this.Menu.GetConfigAsync('HelperDescrip', init); + } + }; + + /** + * 帮助接口 + */ + public Help = { + /** + * 故障报告 /api/Help/FaultReporting + * @param request 故障报告请求 + * @param init 请求初始化,可选。 + * @returns 故障报告结果 + */ + FaultReportingAsync: async (request: FaultReportingRequest, init?: RequestInit): Promise> => { + const response = await fetch(`${this.host}/EIAC_Desktop_Api/api/Help/FaultReporting`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + body: JSON.stringify(request), + ...init + }); + + return await response.json() as ApiResponse; + } + }; } /** * API 响应 */ export interface ApiResponse { - /** - * 状态。0:成功,非0:失败 - */ - status: number; - /** - * HTTP状态码 - */ - code: number; - /** - * 状态消息 - */ - msg: string; - /** - * 数据 - */ - data: T; + /** + * 状态。0:成功,非0:失败 + */ + status: number; + /** + * HTTP状态码 + */ + code: number; + /** + * 状态消息 + */ + msg: string; + /** + * 数据 + */ + data: T; } /** * 登录请求 */ export interface LoginRequest { - /** - * 账号 - */ - Account: string; - /** - * 密码 - */ - Password: string; + /** + * 账号 + */ + Account: string; + /** + * 密码 + */ + Password: string; } /** * 登录响应 */ export interface LoginResponse { - /** - * 是否需要发送短信 - */ - IsNeedSendSMS: boolean; - /** - * 令牌 - */ - Token: string; - /** - * Cookies - */ - Cookies: Array<{ Key: string, Value: string }>; + /** + * 是否需要发送短信 + */ + IsNeedSendSMS: boolean; + /** + * 令牌 + */ + Token: string; + /** + * Cookies + */ + Cookies: Array<{ Key: string, Value: string }>; } /** * 菜单项 */ export interface MenuItem { - /** - * 显示名称 - */ - ShowName: string; - /** - * 菜单链接 - */ - Url: string; - /** - * 图标配置 - */ - IconConfig: IconConfig; - /** - * 子菜单 - */ - Children: MenuItem[] | null; + /** + * 显示名称 + */ + ShowName: string; + /** + * 菜单链接 + */ + Url: string; + /** + * 图标配置 + */ + IconConfig: IconConfig; + /** + * 子菜单 + */ + Children: MenuItem[] | null; } /** * 图标配置 */ export interface IconConfig { + /** + * 1x 图标 + */ + _1x: { /** - * 1x 图标 + * 默认图标 */ - _1x: { - /** - * 默认图标 - */ - Default: string; - /** - * 选中图标 - */ - Selected: string; - }; + Default: string; /** - * 2x 图标 + * 选中图标 */ - _2x: { - /** - * 默认图标 - */ - Default: string; - /** - * 选中图标 - */ - Selected: string; - }; + Selected: string; + }; + /** + * 2x 图标 + */ + _2x: { + /** + * 默认图标 + */ + Default: string; + /** + * 选中图标 + */ + Selected: string; + }; } /** * TagResolution 配置项 */ export interface TagResolutionConfig { - /** - * 分辨率列表,以','分隔 - */ - Resolutions: string; - /** - * 缩放比例 - */ - Percentage: string | number; - /** - * 特殊页面 - */ - SpecialPUrl: SpecialPUrlItem[]; + /** + * 分辨率列表,以','分隔 + */ + Resolutions: string; + /** + * 缩放比例 + */ + Percentage: string | number; + /** + * 特殊页面 + */ + SpecialPUrl: SpecialPUrlItem[]; } /** * 特殊页面的缩放比例配置项 */ export interface SpecialPUrlItem { - /** - * 特殊页面URL - */ - SPUrl: string; - /** - * 特殊页面缩放比例 - */ - SPPer: string | number; + /** + * 特殊页面URL + */ + SPUrl: string; + /** + * 特殊页面缩放比例 + */ + SPPer: string | number; +} + +/** + * 帮助描述 + */ +export interface HelperDescription { + /** + * HTTP状态码,例如:403。*表示在匹配不到可用的状态码时使用。 + */ + Code: string; + /** + * 描述 + */ + Descrip: string; } /** * 故障报告请求 */ export interface FaultReportingRequest { - /** - * IP - */ - IP: string; - /** - * 页面URL - */ - Url: string; - /** - * 账号 - */ - Account: string; - /** - * 图片Base64 - */ - ImgBase64: string; - /** - * 说明 - */ - Explain: string; + /** + * IP + */ + IP: string; + /** + * 页面URL + */ + Url: string; + /** + * 账号 + */ + Account: string; + /** + * 图片Base64 + */ + ImgBase64: string; + /** + * 说明 + */ + Explain: string; } /** * 故障报告响应 */ export interface FaultReportingResponse { - /** - * 故障报告ID - */ - FaultReportingId: string; + /** + * 故障报告ID + */ + FaultReportingId: string; } export const EIACDesktopApi = new EIAC_Desktop_Api(); \ No newline at end of file diff --git a/src/IpcMainHandler.ts b/src/IpcMainHandler.ts index 5cc9d29..c14bf77 100644 --- a/src/IpcMainHandler.ts +++ b/src/IpcMainHandler.ts @@ -3,29 +3,45 @@ import http from 'http'; import https from 'https'; import os from 'os'; import { URL } from 'url'; -import { ApiResponse, MenuItem, TagResolutionConfig, EIACDesktopApi, SpecialPUrlItem, FaultReportingResponse } from './EIAC_Desktop_Api'; +import { ApiResponse, MenuItem, TagResolutionConfig, EIACDesktopApi, SpecialPUrlItem, FaultReportingResponse, HelperDescription } from './EIAC_Desktop_Api'; const memoryCache = new Map(); export function initialize(): void { // Set cache - ipcMain.handle('cache:set', (_event, key: string, value: any) => { + ipcMain.handle('cache:set', (_event, key: string, value: any): void => { memoryCache.set(key, value); }); // Get cache - ipcMain.handle('cache:get', (_event, key: string) => { + ipcMain.handle('cache:get', (_event, key: string): any | null => { return memoryCache.get(key) ?? null; }); // Get menu cache ipcMain.handle('get-menu-cache', async () => menuData ?? await menuDataReadyPromise); - // Get config cache - ipcMain.handle('get-config-cache', async () => configData ?? await configDataReadyPromise); + // Get helper descrip by code + ipcMain.handle('get-helper-descrip', async (event, code: string): Promise => { + if (!helperDescriptionData) { + await helperDescriptionDataReadyPromise; + } + + if (helperDescriptionData.code != 200 || helperDescriptionData.status != 0) { + console.error('Get config failed:', helperDescriptionData.msg + ', status: ' + helperDescriptionData.status + ', code: ' + helperDescriptionData.code); + return null; + } + + let helperDescrip: HelperDescription | null = helperDescriptionData.data.find(h => h.Code === code); + if (!helperDescrip) { + helperDescrip = helperDescriptionData.data.find(h => h.Code === '*'); + } + + return helperDescrip ? helperDescrip.Descrip : null; + }); // Get zoom factor - ipcMain.handle('get-zoom-factor-by-url', async (event, url: string) => { + ipcMain.handle('get-zoom-factor-by-url', async (event, url: string): Promise => { const display: Electron.Display = screen.getPrimaryDisplay(); const physicalSize: Electron.Size = { width: display.size.width * display.scaleFactor, @@ -36,16 +52,16 @@ export function initialize(): void { console.log(`Resolution: ${display.size.width}*${display.size.height}`); console.log(`ScaleFactor: ${display.scaleFactor}`); - if (!configData) { - await configDataReadyPromise; + if (!tagResolutionData) { + await tagResolutionDataReadyPromise; } - if (configData.code != 200 || configData.status != 0) { - console.error('Get config failed:', configData.msg + ', status: ' + configData.status + ', code: ' + configData.code); + if (tagResolutionData.code != 200 || tagResolutionData.status != 0) { + console.error('Get config failed:', tagResolutionData.msg + ', status: ' + tagResolutionData.status + ', code: ' + tagResolutionData.code); return display.scaleFactor; } - const configList: TagResolutionConfig[] = configData.data; + const configList: TagResolutionConfig[] = tagResolutionData.data; let config: TagResolutionConfig = configList.find(c => c.Resolutions.includes(resolution)); if (!config) { config = configList.find(c => c.Resolutions === '*'); @@ -71,7 +87,7 @@ export function initialize(): void { }); // Check if the URL is available - ipcMain.handle('check-url-available', async (event, rawUrl: string) => { + ipcMain.handle('check-url-available', async (event, rawUrl: string): Promise<{ ok: boolean, status: number, message: string }> => { try { const url: URL = new URL(rawUrl); const lib = url.protocol === 'https:' ? https : http; @@ -138,7 +154,7 @@ export function initialize(): void { }); // Set webview‘s cookie - ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string) => { + ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string): Promise => { try { const parsedUrl = new URL(url); const cookies: Array<{ Key: string, Value: string }> = JSON.parse(cookie); @@ -162,7 +178,7 @@ export function initialize(): void { }); // Fault reporting - ipcMain.handle('fault-reporting', async (event, url: string, message: string, status: number) => { + ipcMain.handle('fault-reporting', async (event, url: string, message: string, status: number): Promise<{ ok: boolean, status: number, message: string }> => { console.log('Fault reporting:', url, message, status); const webContents = event.sender; @@ -197,6 +213,10 @@ export function initialize(): void { }); } +/** + * 获取本机IP地址 + * @returns 本机IP地址 + */ function getLocalIPAddress(): string | null { const interfaces = os.networkInterfaces(); @@ -212,6 +232,11 @@ function getLocalIPAddress(): string | null { return null; // 没有找到 } +/** + * 捕获当前窗口并且转换为Base64格式的图像 + * @param win 窗口 + * @returns 返回Base64格式的图像 + */ async function captureWindowAsBase64(win: BrowserWindow): Promise { const image = await win.capturePage(); // 截图 const pngBuffer = image.toPNG(); // 转为 PNG Buffer @@ -221,9 +246,14 @@ async function captureWindowAsBase64(win: BrowserWindow): Promise { let menuData: ApiResponse = null; let menuDataReadyPromise: Promise>; -let configData: ApiResponse = null; -let configDataReadyPromise: Promise>; +let tagResolutionData: ApiResponse = null; +let tagResolutionDataReadyPromise: Promise>; +let helperDescriptionData: ApiResponse = null; +let helperDescriptionDataReadyPromise: Promise>; +/** + * 获取菜单数据 + */ function getMenuAsync(): void { if (!menuDataReadyPromise) { menuDataReadyPromise = new Promise((resolve, reject) => { @@ -239,12 +269,15 @@ function getMenuAsync(): void { } } -function getConfigAsync(): void { - if (!configDataReadyPromise) { - configDataReadyPromise = new Promise((resolve, reject) => { - EIACDesktopApi.Menu.GetConfigAsync() +/** + * 获取分辨率配置 + */ +function getTagResolutionsAsync(): void { + if (!tagResolutionDataReadyPromise) { + tagResolutionDataReadyPromise = new Promise((resolve, reject) => { + EIACDesktopApi.Menu.GetTagResolutionsAsync() .then(data => { - configData = data; + tagResolutionData = data; resolve(data); }) .catch(err => { @@ -254,7 +287,29 @@ function getConfigAsync(): void { } } +/** + * 获取帮助描述 + */ +function getHelperDescriptionsAsync(): void { + if (!helperDescriptionDataReadyPromise) { + helperDescriptionDataReadyPromise = new Promise((resolve, reject) => { + EIACDesktopApi.Menu.GetHelperDescripsAsync() + .then(data => { + helperDescriptionData = data; + resolve(data); + }) + .catch(err => { + reject(err); + }); + }); + } +} + +/** + * 预加载数据 + */ export function preloadData(): void { getMenuAsync(); - getConfigAsync(); + getTagResolutionsAsync(); + getHelperDescriptionsAsync(); } diff --git a/src/index.ts b/src/index.ts index 4c6dd34..4673062 100644 --- a/src/index.ts +++ b/src/index.ts @@ -129,7 +129,9 @@ async function addTabAsync(tabGroup: TabGroup, menuItem: MenuItem): Promise { await addTabAsync(tabGroup, firstMenuItem); // Bind logo click event - const lastMenuItem: MenuItem = menuList[menuList.length - 1]; - const logoMenuItem: MenuItem = lastMenuItem.Children[lastMenuItem.Children.length - 1]; + const logoMenuItem: MenuItem = menuList[menuList.length - 1]; bindLogoClickEvent(tabGroup, logoMenuItem); // Bind logout event diff --git a/src/preload.ts b/src/preload.ts index 78ab07e..c9c8b94 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -24,10 +24,11 @@ contextBridge.exposeInMainWorld('electronAPI', { getMenuCacheAsync: () => ipcRenderer.invoke('get-menu-cache') as Promise>, /** - * 获取配置缓存 - * @returns 配置缓存 + * 获取帮助描述 + * @param code 帮助描述代码 + * @returns 帮助描述 */ - getConfigCacheAsync: () => ipcRenderer.invoke('get-config-cache') as Promise>, + getHelperDescripAsync: (code: string) => ipcRenderer.invoke('get-helper-descrip', code) as Promise, /** * 获取指定URL的缩放比例 diff --git a/src/types/electron.d.ts b/src/types/electron.d.ts index 5500b27..6d91353 100644 --- a/src/types/electron.d.ts +++ b/src/types/electron.d.ts @@ -19,10 +19,11 @@ export interface ElectronAPI { */ getMenuCacheAsync: () => Promise>; /** - * 获取配置缓存 - * @returns 配置缓存 + * 获取帮助描述 + * @param code 帮助描述代码 + * @returns 帮助描述 */ - getConfigCacheAsync: () => Promise>; + getHelperDescripAsync: (code: string) => Promise; /** * 获取指定URL的缩放比例 * @param url 要获取缩放比例的URL