Quellcode durchsuchen

增加宽屏比例支持显示右侧栏功能

快乐的梦鱼 vor 3 Tagen
Ursprung
Commit
1951e87f7f

+ 2 - 1
.claude/settings.local.json

@@ -1,7 +1,8 @@
 {
   "permissions": {
     "allow": [
-      "Bash(npx vue-tsc *)"
+      "Bash(npx vue-tsc *)",
+      "Bash(npx tsc *)"
     ]
   }
 }

+ 1 - 0
apps.json

@@ -5,6 +5,7 @@
       "title": "闽南文化驾驶舱",
       "keepScreenSize": true,
       "aspectRatio": "16/9",
+      "sideUrl": "https://www.ourtoolset.com/calendar",
       "openType": "iframe",
       "url": "https://mn.wenlvti.net/test/#/",
       "inputPassword": {

+ 1 - 1
electron/electron-env.d.ts

@@ -32,7 +32,7 @@ interface Window {
     loadDefaultAppsJson: () => Promise<any>
     saveAppsJson: (appsJson: string) => void
     openWindow: (url: string) => void
-    loadChildUrl: (url: string, aspectRatio: number, inputPassword?: { username: string; password: string }) => void
+    loadChildUrl: (url: string, aspectRatio: number, inputPassword?: { username: string; password: string }, sideUrl?: string) => void
     toggleChildSide: (isSideOen: boolean) => void
     showConfig: () => void
     showAbout: () => void

+ 61 - 23
electron/main.ts

@@ -31,9 +31,11 @@ type InputPassword = {
 
 let mainWindow: BrowserWindow | null
 let childView: WebContentsView | null
+let childSideView: WebContentsView | null
 
 let isSideOpen = true
 let childViewAspectRatio = 0; 
+let childViewSideUrl : string | undefined;
 let childViewInputPassword: InputPassword | undefined;
 const SIDE_WIDTH = 250
 const EXPAND_VIEW_SIZE = 40
@@ -82,37 +84,40 @@ function createWindow() {
       allowRunningInsecureContent: true,
     },
   })
+  childSideView = new WebContentsView({
+    webPreferences: {
+      allowRunningInsecureContent: true,
+    },
+  })
   const expandButtonView = new WebContentsView({
     webPreferences: {
       preload: path.join(__dirname, 'preload.mjs'),
       contextIsolation: true,
     },
   })
-  const loadingView = new BrowserWindow({
-    skipTaskbar: true,
-    width: LOADING_VIEW_WIDTH,
-    height: LOADING_VIEW_HEIGHT,
-    parent: mainWindow,
-    thickFrame: true,
-    titleBarStyle: 'hidden',
+  const loadingView = new WebContentsView({
     webPreferences: {
       preload: path.join(__dirname, 'preload.mjs'),
       contextIsolation: true,
     },
   })
   mainWindow.contentView.addChildView(childView)
+  mainWindow.contentView.addChildView(childSideView)
   mainWindow.contentView.addChildView(expandButtonView)
-  expandButtonView.setVisible(false)  
+  mainWindow.contentView.addChildView(loadingView)
+  expandButtonView.setVisible(false)
+  childSideView.setVisible(false)
+  loadingView.setBackgroundColor('#00000000')
   expandButtonView.setBackgroundColor('#00000000')
 
   childView.webContents.on('did-start-loading', () => {
-    loadingView.show()
+    loadingView.setVisible(true)
   });
   childView.webContents.on('did-stop-loading', () => {
-    loadingView.hide()
+    loadingView.setVisible(false)
   });
   childView.webContents.on('did-fail-load', (_, errorCode, errorDescription) => {
-    loadingView.hide()
+    loadingView.setVisible(false)
     loadViewUrl(childView!, '/error?code=' + errorCode + '&message=' + errorDescription);
   });
 
@@ -129,8 +134,8 @@ function createWindow() {
       height: EXPAND_VIEW_SIZE
     })
     loadingView.setBounds({
-      x: bounds.x + (bounds.width - LOADING_VIEW_WIDTH) / 2,
-      y: bounds.y + 30,
+      x: (bounds.width - LOADING_VIEW_WIDTH) / 2,
+      y: 30,
       width: LOADING_VIEW_WIDTH,
       height: LOADING_VIEW_HEIGHT
     })
@@ -151,15 +156,33 @@ function createWindow() {
         childHeight = childWidth / childViewAspectRatio;
       }
 
-      const childX = availableX + (availableWidth - childWidth) / 2;
-      const childY = (availableHeight - childHeight) / 2;
+      const remainingWidth = availableWidth - childWidth;
+      if (childHeight === availableHeight && remainingWidth > 0 && childViewSideUrl) {
+        childView!.setBounds({
+          x: availableX,
+          y: 0,
+          width: Math.round(childWidth),
+          height: Math.round(childHeight)
+        });
+        childSideView!.setBounds({
+          x: availableX + Math.round(childWidth),
+          y: 0,
+          width: Math.round(remainingWidth),
+          height: Math.round(availableHeight)
+        });
+        childSideView!.setVisible(true);
+      } else {
+        const childX = availableX + (availableWidth - childWidth) / 2;
+        const childY = (availableHeight - childHeight) / 2;
 
-      childView!.setBounds({
-        x: Math.round(childX),
-        y: Math.round(childY),
-        width: Math.round(childWidth),
-        height: Math.round(childHeight)
-      });
+        childView!.setBounds({
+          x: Math.round(childX),
+          y: Math.round(childY),
+          width: Math.round(childWidth),
+          height: Math.round(childHeight)
+        });
+        childSideView!.setVisible(false);
+      }
     } else {
       childView!.setBounds({
         x: availableX,
@@ -167,11 +190,12 @@ function createWindow() {
         width: availableWidth,
         height: availableHeight
       });
+      childSideView!.setVisible(false);
     }
   }
 
   loadWindowPage(mainWindow, '/');
-  loadWindowPage(loadingView, '/loading');
+  loadViewUrl(loadingView, '/loading');
   loadViewUrl(childView, '/hello');
   loadViewUrl(expandButtonView, '/expand');
   updateChildWindowBounds();
@@ -280,11 +304,21 @@ function createWindow() {
   })
   ipcMain.on('toggle-dev-tools', toggleDevTools)
   // 加载子页URL
-  ipcMain.on('load-child-url', (_event, url: string, aspectRatio: number, inputPassword?: InputPassword) => {
+  ipcMain.on('load-child-url', (_event, url: string, aspectRatio: number, inputPassword?: InputPassword, sideUrl?: string) => { 
     if (childView)
       childView.webContents.loadURL(url)
+    if (childSideView) {
+      if (sideUrl) {
+        childSideView.webContents.loadURL(sideUrl)
+      } else {
+        childSideView.setVisible(false)
+      }
+    }
+
+    childViewSideUrl = sideUrl
     childViewInputPassword = inputPassword;
     childViewAspectRatio = aspectRatio
+
     updateChildWindowBounds()
   })
   // 子页侧边栏开关
@@ -413,6 +447,10 @@ function createWindow() {
         await childView.webContents.session.clearCache()
         childView.webContents.reloadIgnoringCache();
       }
+      if (childSideView && childViewSideUrl) {
+        await childSideView.webContents.session.clearCache()
+        childSideView.webContents.reloadIgnoringCache();
+      }
     }
   })
 

+ 1 - 1
electron/preload.ts

@@ -32,7 +32,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
   loadDefaultAppsJson: () => ipcRenderer.invoke('load-default-apps-json'),
   saveAppsJson: (appsJson: string) => ipcRenderer.send('save-apps-json', appsJson),
   openWindow: (url: string) => ipcRenderer.send('open-window', url),
-  loadChildUrl: (url: string, aspectRatio: number, inputPassword?: { username: string; password: string }) => ipcRenderer.send('load-child-url', url, aspectRatio, inputPassword),
+  loadChildUrl: (...params: any[]) => ipcRenderer.send('load-child-url', ...params),
   toggleChildSide: (isSideOen: boolean) => ipcRenderer.send('toggle-child-side', isSideOen),
   showConfig: () => ipcRenderer.send('show-config'),
   showAbout: () => ipcRenderer.send('show-about'),

+ 1 - 1
src/config/version.json

@@ -1,5 +1,5 @@
 {
   "version": "1.0.3",
-  "versionCode": 24,
+  "versionCode": 25,
   "buildDate": "2026-07-01"
 }

+ 4 - 0
src/model/App.ts

@@ -19,6 +19,10 @@ export interface AppItem {
    * 屏幕尺寸比例。例如 16 / 9
    */
   aspectRatio?: string
+  /** 
+   * 应用侧边栏URL,仅在设置了屏幕尺寸比例且右侧有空余空间时有效
+   */
+  sideUrl?: string
   /**
    * 自动输入用户名与密码
    */

+ 5 - 2
src/views/Config.vue

@@ -40,7 +40,8 @@
           <ul class="help-list">
             <li><code>keepScreenSize</code>: 是否保持显示尺寸比例(布尔类型,默认false)</li>
             <li><code>aspectRatio</code>: 屏幕尺寸比例(字符串类型,例如 "16/9")</li>
-            <li><code>inputPassword</code>: 自动输入用户名与密码(对象类型,例如 {"username": "admin", "password": "123456"})</li>
+            <li><code>sideUrl</code>: 应用侧边栏URL(字符串类型),仅在设置了<code>keepScreenSize</code>和<code>aspectRatio</code>且右侧有空余空间时显示</li>
+            <li><code>inputPassword</code>: 自动输入用户名与密码(需要打开到登录页面才能自动输入)(对象类型,例如 {"username": "admin", "password": "123456"})</li>
           </ul>
         </div>       
         <div class="help-section">
@@ -54,6 +55,7 @@
           <ul class="help-list">
             <li>URL必须是完整的地址(包含http://或https://)</li>
             <li>设置<code>keepScreenSize</code>为true时,建议同时设置<code>aspectRatio</code></li>
+            <li>设置<code>sideUrl</code>时,需同时设置<code>keepScreenSize</code>和<code>aspectRatio</code>,当窗口宽度有剩余空间时侧边栏会显示在右侧</li>
             <li>修改配置后点击"保存配置"按钮生效</li>
           </ul>
         </div>
@@ -86,7 +88,8 @@ const configExample = ref(`{
       "title": "百度",
       "url": "https://www.baidu.com",
       "keepScreenSize": true,
-      "aspectRatio": "16/9"
+      "aspectRatio": "16/9",
+      "sideUrl": "https://www.example.com"
     },
     {
       "id": 3,

+ 8 - 1
src/views/Loading.vue

@@ -6,6 +6,11 @@
 </template>
 
 <style lang="scss">
+html {
+  background-color: transparent;
+  margin: 0;
+  padding: 0;
+}
 .loading-container {
   padding: 10px;
   display: flex;
@@ -13,10 +18,12 @@
   align-items: center;
   justify-content: center;
   gap: 10px;
+  background-color: rgba(0, 0, 0, 0.5);
+  border-radius: 10px;
 
   span {
-    margin-top: 10px;
     font-size: 14px;
+    color: #fff;
   }
 }
 </style>

+ 11 - 6
src/views/Main.vue

@@ -65,12 +65,17 @@ function selectApp(app: AppItem) {
     }
 
     document.title = app.title;
-    window.electronAPI.loadChildUrl(app.url, app.keepScreenSize ? (
-      parseAspectRatio(app.aspectRatio || '16:9')
-    ) : 0, app.inputPassword ? {
-      username: app.inputPassword.username,
-      password: app.inputPassword.password,
-    } : undefined)
+    window.electronAPI.loadChildUrl(
+      app.url, 
+      app.keepScreenSize ? (
+        parseAspectRatio(app.aspectRatio || '16:9')
+      ) : 0, 
+      app.inputPassword ? {
+        username: app.inputPassword.username,
+        password: app.inputPassword.password,
+      } : undefined, 
+      app.sideUrl
+    )
   //}
   setTimeout(() => {
     isLoading.value = false

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
tsconfig.node.tsbuildinfo