yichael 5 miesięcy temu
rodzic
commit
d0987bd31c

BIN
BugList.xlsx


+ 23 - 0
README.md

@@ -34,3 +34,26 @@
 - **间距内边距**:`rem` 或 `%`
 - **关键尺寸**:`vw` 或 `%`
 - **布局控制**:Flexbox + 媒体查询断点
+
+**五、媒体查询器**
+
+- **桌面端适配**:
+  - 最小值 = 1024px × 20% = 204.8px ≈ 200px(1024 是 PC 的最小尺寸)
+  - 最大值 = 1920px × 20% = 384px ≈ 400px(1920 是 PC 的最大尺寸)
+  
+  ```css
+  .devices-container {
+    width: clamp(200px, 20%, 400px);
+    height: 100%;
+  }
+  ```
+
+- **平板适配**:
+  - 最小值 = 768px × 20% = 153.6px ≈ 150px(768px 是平板端媒体查询的最小宽度)
+  - 最大值 = 300px(设计限制,不是计算出来的)
+  
+  ```css
+  .devices-container {
+    width: clamp(150px, 20%, 300px);
+  }
+  ```

+ 26 - 7
src/App.css

@@ -1,29 +1,48 @@
+:root {
+  /* Responsive root font size: clamps between 14px and 18px based on viewport width */
+  font-size: clamp(14px, 1vw + 12px, 18px);
+}
+
+:root {
+  height: 100%;
+}
+
+html, body, #root {
+  height: 100%;
+  margin: 0;
+  overflow: hidden; /* prevent page scrollbars */
+}
+
 .app {
-  padding: 20px;
+  width: 100vw;
   height: 100vh;
+  padding: 0; /* move padding to inner container to avoid overflow with 100vw/100vh */
+  box-sizing: border-box;
+  overflow: hidden;
 }
 
 h1 {
-  margin-bottom: 20px;
+  margin-bottom: clamp(12px, 1.5vw, 20px);
   color: #2c3e50;
+  font-size: clamp(1.2rem, 2vw + 0.5rem, 2rem);
 }
 
 .container {
   background: white;
   border-radius: 8px;
-  padding: 30px;
+  padding: clamp(20px, 2vw + 10px, 32px);
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
   text-align: center;
 }
 
 button {
-  margin-top: 20px;
-  padding: 10px 20px;
-  font-size: 16px;
+  margin-top: clamp(12px, 2vw, 20px);
+  padding: clamp(8px, 1vw + 6px, 12px) clamp(14px, 2vw + 8px, 22px);
+  font-size: clamp(0.85rem, 0.8vw + 0.6rem, 1rem);
   background-color: #007bff;
   color: white;
   border: none;
-  border-radius: 4px;
+  border-radius: 6px;
   cursor: pointer;
   transition: background-color 0.3s;
 }

+ 0 - 2
src/App.jsx

@@ -1,11 +1,9 @@
 import './App.css';
 import Home from './pages/Home.jsx';
-import ScreenShot from './pages/ScreenShot/ScreenShot.jsx';
 function App() {
   return (
     <div className="app">
       <Home />
-      <ScreenShot />
     </div>
   );
 }

+ 60 - 28
src/pages/Devices/Devices.css

@@ -4,60 +4,68 @@
 .Devices-container {
   width: 100%;
   height: 100%;
-  box-sizing: border-box;
+
   display: flex;
+  box-sizing: border-box;
   flex-direction: column;
+  align-items: flex-start;
   background: #f8f9fa;
-  padding: clamp(0.75rem, 2vw, 1.5rem);
+  /* padding: clamp(0.75rem, 2vw, 1.5rem); */
 }
 
 /* 头部区域 */
 .devices-header {
   width: 100%;
-  box-sizing: border-box;
-  display: flex;
-  justify-content: space-between;
+  display: grid;
+  grid-template-columns: 65% 35%;
   align-items: center;
   gap: clamp(0.5rem, 1.5vw, 1rem);
-  margin-bottom: clamp(0.75rem, 2vw, 1.5rem);
-  padding: clamp(0.5rem, 1.5vw, 1rem);
+  box-sizing: border-box;
   border: 1px solid #e5e7eb;
   border-radius: clamp(6px, 1vw, 8px);
   background: #ffffff;
   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
-  min-height: clamp(40px, 6vw, 48px);
+  container-type: inline-size; /* enable cqw-based scaling */
+  padding: clamp(0.5rem, 1.5vw, 1rem);
 }
 
 /* 标题 */
 .devices-title {
-  font-size: clamp(1rem, 2.5vw, 1.8rem);
+  width: 100%; /* takes its 60% grid column */
+  display: flex;
+  box-sizing: border-box;
+  align-items: center;
+
+  font-size: clamp(1rem, 6cqw, 1.9rem);
   font-weight: 600;
-  padding: 0;
   color: #1a1a1a;
   letter-spacing: -0.5px;
   line-height: 1.2;
-  display: flex;
-  align-items: center;
+  white-space: nowrap;
 }
 
 /* 刷新按钮 */
 .refresh-btn {
+  justify-self: start;
+  width: 80%;
   display: flex;
   align-items: center;
   justify-content: center;
-  gap: clamp(0.25rem, 1vw, 0.5rem);
-  padding: clamp(0.5rem, 1.5vw, 0.625rem) clamp(0.75rem, 2vw, 1.25rem);
+  gap: clamp(0.15rem, 0.8cqw, 0.4rem);
+  padding: clamp(0.36rem, 1.1cqw, 0.6rem) clamp(0.6rem, 1.5cqw, 1rem);
   background: #1a1a1a;
   color: white;
   border: none;
   border-radius: clamp(6px, 1vw, 8px);
   cursor: pointer;
-  font-size: clamp(0.75rem, 1.5vw, 1rem);
+  /* about 80% of original size */
+  font-size: clamp(0.6rem, 2.1cqw, 0.84rem); /* scale text/icon with button */
   font-weight: 500;
   transition: all 0.2s ease;
   line-height: 1.2;
   user-select: none;
   white-space: nowrap;
+  flex-shrink: 0;
 }
 
 .refresh-btn:hover:not(.disabled) {
@@ -81,7 +89,7 @@
 
 /* 刷新图标 */
 .refresh-icon {
-  font-size: 1em;
+  font-size: 1em; /* inherit current button size */
   transition: transform 0.3s ease;
   display: inline-block;
 }
@@ -112,6 +120,8 @@
   overflow-y: auto;
   overflow-x: hidden;
   padding: 0;
+  width: 100%;
+  box-sizing: border-box;
 }
 
 /* 自定义滚动条 */
@@ -134,16 +144,21 @@
 
 /* 设备项 */
 .device-item {
-  display: flex;
-  justify-content: space-between;
+  display: grid;
+  grid-template-columns: 1fr auto; /* text flexes, button keeps size */
   align-items: center;
-  padding: clamp(0.75rem, 1.5vw, 1rem) clamp(0.875rem, 2vw, 1.25rem);
+  width: 100%; /* align with header width */
+  box-sizing: border-box;
+  column-gap: clamp(0.25rem, 0.8vw, 0.6rem);
+  padding: clamp(0.6rem, 1.2vw, 0.85rem) clamp(0.75rem, 1.6vw, 1rem);
   margin-bottom: clamp(0.5rem, 1.5vw, 0.75rem);
   background: white;
   border-radius: clamp(6px, 1vw, 8px);
   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
   transition: all 0.2s ease;
   border: 1px solid #e5e7eb;
+  container-type: inline-size; /* allow cqw-based scaling inside */
+
 }
 
 .device-item:hover {
@@ -152,37 +167,52 @@
   transform: translateY(-1px);
 }
 
+.device-actions {
+  display: flex;
+  flex-direction: column;
+  gap: clamp(0.4rem, 1vw, 0.75rem);
+  align-items: flex-start;
+}
+
 /* 设备信息容器 */
 .device-info {
-  flex: 1;
+  width: 100%;
   min-width: 0;
 }
 
 /* 设备 ID(IP:端口) */
 .device-id {
-  font-size: clamp(0.8rem, 1.8vw, 1.1rem);
+  /* scale with device-item width */
+  width: 100%;
+  font-size: clamp(0.5rem, 1.6cqw, 0.85rem);
   font-weight: 500;
   color: #1a1a1a;
   font-family: 'Courier New', 'Consolas', monospace;
-  word-break: break-all;
-  letter-spacing: 0.2px;
+  word-break: keep-all;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: clip;
+  letter-spacing: 0;
   line-height: 1.5;
 }
 
 /* 连接按钮 */
 .connect-btn {
-  padding: clamp(0.5rem, 1.5vw, 0.625rem) clamp(0.75rem, 2vw, 1.5rem);
+  /* scale with device-item width */
+  width: auto;
+  padding: clamp(0.32rem, 0.9cqw, 0.5rem) clamp(0.5rem, 1.3cqw, 0.85rem);
   background: #1a1a1a;
   color: white;
   border: none;
   border-radius: clamp(6px, 1vw, 8px);
   cursor: pointer;
-  font-size: clamp(0.75rem, 1.5vw, 1rem);
+  font-size: clamp(0.65rem, 1.6cqw, 0.85rem);
   font-weight: 500;
   transition: all 0.2s ease;
   white-space: nowrap;
-  margin-left: clamp(0.5rem, 1.5vw, 1rem);
+  margin-left: clamp(0.25rem, 1vw, 0.75rem);
   user-select: none;
+  flex-shrink: 0;
 }
 
 .connect-btn:hover:not(.disabled) {
@@ -206,17 +236,19 @@
 
 /* 断开按钮 */
 .disconnect-btn {
-  padding: clamp(0.5rem, 1.5vw, 0.625rem) clamp(0.75rem, 2vw, 1.5rem);
+  /* match connect button sizing */
+  padding: clamp(0.4rem, 1.2cqw, 0.6rem) clamp(0.6rem, 1.8cqw, 1.1rem);
   background: #dc2626;
   color: white;
   border: none;
   border-radius: clamp(6px, 1vw, 8px);
   cursor: pointer;
-  font-size: clamp(0.75rem, 1.5vw, 1rem);
+  font-size: clamp(0.75rem, 2.2cqw, 0.95rem);
   font-weight: 500;
   transition: all 0.2s ease;
   white-space: nowrap;
   user-select: none;
+  flex-shrink: 0;
 }
 
 .disconnect-btn:hover:not(.disabled) {

+ 1 - 1
src/pages/Devices/Devices.jsx

@@ -34,7 +34,7 @@ function Devices() {
             <div className="device-info">
               <div className="device-id">{ipPort}</div>
             </div>
-            <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
+            <div className="device-actions">
               {!connectedDevices.has(ipPort) && (
                 <div 
                   className={`connect-btn ${loading ? 'disabled' : ''}`}

+ 21 - 0
src/pages/ScreenShot/ScreenShot.css

@@ -1,3 +1,24 @@
 .ScreenShot-container {
   padding: 20px;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  box-sizing: border-box;
+  overflow: hidden;
+}
+
+.screenshot-frame {
+  width: min(100%, calc(80vh * 1280 / 2400));
+  height: auto;
+  max-height: 80vh;
+  margin: auto 0; /* vertical centering inside flex container */
+  aspect-ratio: 1280 / 2400;
+  border: 2px dashed #999;
+  background-color: #f5f5f5;
+  box-sizing: border-box;
+  flex-shrink: 0;
+  /* 保持 1280x2400 比例,限制在容器内 */
 }

+ 4 - 1
src/pages/ScreenShot/ScreenShot.jsx

@@ -6,7 +6,10 @@ function ScreenShot() {
 
   return (
     <div className="ScreenShot-container">
-      <h1>ScreenShot</h1>
+      <div className="preview">显示预览</div>
+      <div className="screenshot-frame">
+        {/* 竖屏 2400x1280 灰色线框区域 */}
+      </div>
     </div>
   );
 }

+ 3 - 0
src/pages/Setting/Setting.css

@@ -0,0 +1,3 @@
+.Setting-container {
+  padding: 20px;
+}

+ 7 - 0
src/pages/Setting/Setting.js

@@ -0,0 +1,7 @@
+export function SettingLogic() {
+  // business logic placeholder
+
+  return {
+    // expose data or methods here
+  };
+}

+ 14 - 0
src/pages/Setting/Setting.jsx

@@ -0,0 +1,14 @@
+import './Setting.css';
+import { SettingLogic } from './Setting.js';
+
+function Setting() {
+  const logic = SettingLogic();
+
+  return (
+    <div className="Setting-container">
+      <h1>Setting</h1>
+    </div>
+  );
+}
+
+export default Setting;

+ 12 - 21
src/pages/home.css

@@ -1,27 +1,18 @@
 .Home-container {
-  display: flex;
+  display: grid;
+  grid-template-columns: 20% 50% 30%;
   width: 100vw;
   height: 100vh;
-  /* border: 1px solid #f00303; */
+  box-sizing: border-box;
+  align-items: stretch;
+  padding: clamp(12px, 2vw, 24px);
+  overflow: hidden; /* prevent internal scrollbars */
+  container-type: inline-size; /* enable cqw-based scaling */
 }
 
-.side-bar {
-  width: clamp(250px, 30%, 400px);
-  height: 100%;
-  min-width: 200px;
-}
-
-/* 平板适配 */
-@media (min-width: 768px) and (max-width: 1023px) {
-  .side-bar {
-    width: clamp(200px, 35%, 350px);
-  }
-}
-
-/* 移动端适配 */
-@media (max-width: 767px) {
-  .side-bar {
-    width: 100%;
-    min-width: unset;
-  }
+.devices-container,
+.screenshot-container,
+.setting-container {
+  width: 100%;
+  box-sizing: border-box;
 }

+ 6 - 0
src/pages/home.js

@@ -3,10 +3,16 @@ import { useState, useEffect } from 'react';
 export function HomeLogic() {
 
   const [showDevices, setShowDevices] = useState(true);
+  const [showScreenShot, setShowScreenShot] = useState(true);
+  const [showSetting, setShowSetting] = useState(true);
 
   return {
     showDevices,
     setShowDevices,
+    showScreenShot,
+    setShowScreenShot,
+    showSetting,
+    setShowSetting,
     // expose data or methods here
   };
 }

+ 16 - 2
src/pages/home.jsx

@@ -1,15 +1,29 @@
 import './Home.css';
 import { HomeLogic } from './Home.js';
 import Devices from './Devices/Devices.jsx';
+import ScreenShot from './ScreenShot/ScreenShot.jsx';
+import Setting from './Setting/Setting.jsx';
 
 function Home() {
-  const { showDevices, setShowDevices } = HomeLogic();
+  const { showDevices, 
+    setShowDevices, 
+    showScreenShot, 
+    setShowScreenShot,
+    showSetting,
+    setShowSetting,
+  } = HomeLogic();
 
   return (
     <div className="Home-container">
-      <div className="side-bar">
+      <div className="devices-container">
         {showDevices && <Devices />}
       </div>
+      <div className="screenshot-container">
+        {showScreenShot && <ScreenShot />}
+      </div>
+      <div className="setting-container">
+        {showSetting && <Setting />}
+      </div>
     </div>
   );
 }