cc 6 days ago
parent
commit
c72de7e5c0

+ 25 - 9
ai-electron/frontend/src/core/layouts/default/header/index.less

@@ -12,7 +12,10 @@
   position: relative;
   display: flex;
   height: @header-height;
-  padding: 0;
+
+  /* 右侧留 8px:与公共顶栏 AppTopBar(.app-topbar padding: 0 8px 0 0)对齐,
+     否则传统壳右缘内边距被清零、智能壳保留 8px,窗口控制三个按钮在两种模式间横向跳动 */
+  padding: 0 8px 0 0;
   margin-left: -1px;
   line-height: @header-height;
   color: @white;
@@ -211,7 +214,11 @@
   &-action {
     display: flex;
     min-width: 180px;
-    padding-right: 12px;
+
+    /* 与公共顶栏 AppTopBar 的 .app-topbar__actions(padding-right: 4px)对齐:
+       两条规则落同一个元素,这里若保持 12px 会按样式块加载顺序覆盖 4px,
+       导致没加载本文件的智能壳与加载后的按钮组距右缘差 8px */
+    padding-right: 4px;
     align-items: center;
     flex-shrink: 0;
     margin-left: auto;
@@ -259,12 +266,21 @@
       cursor: default;
     }
 
-    // 窗口控制按钮自己管 hover,取消 action 容器统一套上的圆角块
+    // 窗口控制按钮自己管 hover,取消 action 容器统一套上的圆角块。
+    // 这里同时把上面 > div / > span 和 span[role=img] 两条通配规则
+    // 泄漏进窗口控制的 line-height / font-size / 图标内边距一并还原,
+    // 保证按钮在(加载了本文件的)传统壳与(未加载的)智能壳下渲染完全一致。
     > .window-controls-item {
       height: auto;
       padding: 0;
       border-radius: 0;
       cursor: default;
+      font-size: 14px;
+      line-height: normal;
+
+      span[role='img'] {
+        padding: 0;
+      }
     }
 
     span[role='img'] {
@@ -463,8 +479,8 @@
 
     .@{header-prefix-cls}-action {
       /* 同上:模式切换开关的图标保持组件给的 13px,不吃这里的放大规则 */
-      > div:not(.jeesite-workbench-switch),
-      > span:not(.jeesite-workbench-switch) {
+      > div:not(.jeesite-workbench-switch):not(.window-controls-item),
+      > span:not(.jeesite-workbench-switch):not(.window-controls-item) {
         color: @text-color-base;
 
         .jeesite-icon {
@@ -540,8 +556,8 @@
 
     .@{header-prefix-cls}-action {
       /* 同上:模式切换开关的图标保持组件给的 13px,不吃这里的放大规则 */
-      > div:not(.jeesite-workbench-switch),
-      > span:not(.jeesite-workbench-switch) {
+      > div:not(.jeesite-workbench-switch):not(.window-controls-item),
+      > span:not(.jeesite-workbench-switch):not(.window-controls-item) {
         .jeesite-icon {
           padding: 0 10px;
           font-size: 20px !important;
@@ -586,8 +602,8 @@ html[data-theme='dark'] {
   .@{header-prefix-cls} {
     &--dark {
       .@{header-prefix-cls}-action {
-        > div:not(.jeesite-workbench-switch),
-        > span:not(.jeesite-workbench-switch) {
+        > div:not(.jeesite-workbench-switch):not(.window-controls-item),
+        > span:not(.jeesite-workbench-switch):not(.window-controls-item) {
           &:hover {
             background-color: #262626;
           }

+ 2 - 2
ai-electron/frontend/src/core/utils/desktop/downloader.ts

@@ -60,9 +60,9 @@ export interface DownloadListResult {
 /** 桌面端才有下载管理器;浏览器里退回浏览器另存 */
 export const isDesktopDownloadAvailable = () => isDesktopDialogAvailable();
 
-/** 解包信封:失败抛错,调用方负责提示 */
+/** 解包信封:失败抛错,调用方负责提示(方法注册在 downloadCtl 控制器下,通道为 controller/downloadCtl/<method>) */
 async function callDownload<T>(method: string, params?: unknown): Promise<T> {
-  const result = await invokeIpc<DownloadRpc<T>>(method, params);
+  const result = await invokeIpc<DownloadRpc<T>>(method, params, 'downloadCtl');
   if (!result) throw new Error(`桌面端无响应:${method}`);
   if (!result.success) throw new Error(result.message || '操作失败');
   return result.data;

+ 6 - 3
ai-electron/frontend/src/core/utils/desktop/ipcRenderer.ts

@@ -24,11 +24,14 @@ export function resolveIpcRenderer(): IpcRendererLike | null {
 /** 当前是否在桌面客户端里(浏览器里读不了本机文件、也存不了本机设置) */
 export const isDesktopDialogAvailable = () => !!resolveIpcRenderer();
 
-/** 调主进程 osCtl 方法;非桌面端抛错,调用方自己决定降级方式 */
-export async function invokeIpc<T>(method: string, params?: unknown): Promise<T> {
+/**
+ * 调主进程控制器方法;非桌面端抛错,调用方自己决定降级方式。
+ * ee-core 按控制器文件名注册通道(controller/<ctl>/<method>),下载等其它控制器需显式传入 ctl。
+ */
+export async function invokeIpc<T>(method: string, params?: unknown, ctl: string = 'osCtl'): Promise<T> {
   const ipcRenderer = resolveIpcRenderer();
   if (!ipcRenderer) throw new Error('当前环境不可用:请在桌面客户端内打开');
-  return (await ipcRenderer.invoke(`${CHANNEL_PREFIX}${method}`, params)) as T;
+  return (await ipcRenderer.invoke(`controller/${ctl}/${method}`, params)) as T;
 }
 
 type IpcListener = (event: unknown, payload: unknown) => void;

+ 3 - 3
ai-server/src/main/resources/application-dev.yaml

@@ -12,18 +12,18 @@ spring:
       strict: false
       datasource:
         master:
-          url: jdbc:postgresql://192.168.0.103:5432/zsjz-ai
+          url: jdbc:postgresql://192.168.0.106:5432/zsjz-ai
           username: postgres
           password: postgres
           driver-class-name: org.postgresql.Driver
   data:
     redis:
-      host: 192.168.0.103
+      host: 192.168.0.106
       port: 6379
 
   elasticsearch:
     # 全文检索(替代原嵌入式 Lucene)。本机单节点默认地址,独立服务器时改 uris 即可
-    uris: http://192.168.0.103:9200
+    uris: http://192.168.0.106:9200
     connection-timeout: 5s
     socket-timeout: 60s
     #username: elastic