Devices.css 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* Devices 页面样式:极简风格,响应式设计 */
  2. /* 主容器 */
  3. .Devices-container {
  4. width: 100%;
  5. height: 100%;
  6. display: flex;
  7. box-sizing: border-box;
  8. flex-direction: column;
  9. align-items: flex-start;
  10. background: #f8f9fa;
  11. /* padding: clamp(0.75rem, 2vw, 1.5rem); */
  12. }
  13. /* 头部区域 */
  14. .devices-header {
  15. width: 100%;
  16. display: grid;
  17. grid-template-columns: 1fr auto;
  18. align-items: center;
  19. gap: clamp(0.5rem, 1.5vw, 1rem);
  20. box-sizing: border-box;
  21. border: 1px solid #e5e7eb;
  22. border-radius: clamp(6px, 1vw, 8px);
  23. background: #ffffff;
  24. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  25. container-type: inline-size; /* enable cqw-based scaling */
  26. padding: clamp(0.5rem, 1.5vw, 1rem);
  27. }
  28. /* 标题 */
  29. .devices-title {
  30. width: 100%; /* takes its 60% grid column */
  31. display: flex;
  32. box-sizing: border-box;
  33. align-items: center;
  34. font-size: clamp(1rem, 6cqw, 1.9rem);
  35. font-weight: 600;
  36. color: #1a1a1a;
  37. letter-spacing: -0.5px;
  38. line-height: 1.2;
  39. white-space: nowrap;
  40. }
  41. /* 刷新按钮 */
  42. .refresh-btn {
  43. justify-self: end;
  44. inline-size: min(100%, clamp(70px, 28cqw, 120px)); /* scale by header width */
  45. max-inline-size: 100%;
  46. min-inline-size: 0;
  47. display: flex;
  48. align-items: center;
  49. justify-content: center;
  50. gap: clamp(0.12rem, 1.2cqw, 0.35rem);
  51. min-height: clamp(30px, 7cqw, 36px);
  52. padding: clamp(0.26rem, 1.1cqw, 0.42rem) clamp(0.42rem, 1.8cqw, 0.82rem); /* shrink padding as header narrows */
  53. background: #1a1a1a;
  54. color: white;
  55. border: none;
  56. border-radius: clamp(6px, 1cqw, 8px);
  57. cursor: pointer;
  58. font-size: clamp(0.48rem, 2.2cqw, 0.82rem); /* text scales with container */
  59. font-weight: 500;
  60. transition: all 0.2s ease;
  61. line-height: 1.1;
  62. user-select: none;
  63. white-space: nowrap;
  64. flex-shrink: 1;
  65. box-sizing: border-box;
  66. overflow: hidden; /* ensure it never spills outside the header */
  67. }
  68. .refresh-btn:hover:not(.disabled) {
  69. background: #333;
  70. transform: translateY(-1px);
  71. }
  72. .refresh-btn:active:not(.disabled) {
  73. transform: translateY(0);
  74. }
  75. .refresh-btn.disabled {
  76. opacity: 1;
  77. cursor: not-allowed;
  78. background: #e5e7eb; /* clearer contrast for loading state */
  79. color: #374151;
  80. }
  81. .refresh-btn.disabled:hover {
  82. transform: none;
  83. background: #e5e7eb;
  84. }
  85. /* 刷新图标 */
  86. .refresh-icon {
  87. font-size: 1em; /* inherit current button size */
  88. transition: transform 0.3s ease;
  89. display: inline-block;
  90. }
  91. /* 悬停时图标旋转 */
  92. .refresh-btn:hover .refresh-icon:not(.spinning) {
  93. transform: rotate(180deg);
  94. }
  95. /* 扫描中图标持续旋转 */
  96. .refresh-icon.spinning {
  97. animation: spin 1s linear infinite;
  98. }
  99. /* 旋转动画 */
  100. @keyframes spin {
  101. from {
  102. transform: rotate(0deg);
  103. }
  104. to {
  105. transform: rotate(360deg);
  106. }
  107. }
  108. /* 滚动区域 */
  109. .devices-scroll-area {
  110. flex: 1;
  111. overflow-y: auto;
  112. overflow-x: hidden;
  113. padding: 0;
  114. width: 100%;
  115. box-sizing: border-box;
  116. }
  117. /* 自定义滚动条 */
  118. .devices-scroll-area::-webkit-scrollbar {
  119. width: 6px;
  120. }
  121. .devices-scroll-area::-webkit-scrollbar-track {
  122. background: transparent;
  123. }
  124. .devices-scroll-area::-webkit-scrollbar-thumb {
  125. background: #d1d5db;
  126. border-radius: 3px;
  127. }
  128. .devices-scroll-area::-webkit-scrollbar-thumb:hover {
  129. background: #9ca3af;
  130. }
  131. /* 设备项 */
  132. .device-item {
  133. display: grid;
  134. grid-template-columns: 1fr auto; /* text flexes, button keeps size */
  135. align-items: center;
  136. width: 100%; /* align with header width */
  137. box-sizing: border-box;
  138. column-gap: clamp(0.25rem, 0.8vw, 0.6rem);
  139. padding: clamp(0.6rem, 1.2vw, 0.85rem) clamp(0.75rem, 1.6vw, 1rem);
  140. margin-bottom: clamp(0.5rem, 1.5vw, 0.75rem);
  141. background: white;
  142. border-radius: clamp(6px, 1vw, 8px);
  143. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  144. transition: all 0.2s ease;
  145. border: 1px solid #e5e7eb;
  146. container-type: inline-size; /* allow cqw-based scaling inside */
  147. }
  148. .device-item:hover {
  149. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  150. border-color: #d1d5db;
  151. transform: translateY(-1px);
  152. }
  153. .device-actions {
  154. display: flex;
  155. flex-direction: column;
  156. gap: clamp(0.4rem, 1vw, 0.75rem);
  157. align-items: flex-start;
  158. }
  159. .action-row {
  160. display: flex;
  161. flex-direction: column;
  162. gap: clamp(0.4rem, 1vw, 0.75rem);
  163. align-items: flex-end;
  164. }
  165. /* 设备信息容器 */
  166. .device-info {
  167. width: 100%;
  168. min-width: 0;
  169. }
  170. /* 设备 ID(IP:端口) */
  171. .device-id {
  172. /* scale with device-item width */
  173. width: 100%;
  174. font-size: clamp(0.45rem, 2.4cqw, 0.85rem);
  175. font-weight: 500;
  176. color: #1a1a1a;
  177. font-family: 'Courier New', 'Consolas', monospace;
  178. overflow-wrap: anywhere;
  179. word-break: break-all;
  180. white-space: normal;
  181. letter-spacing: 0;
  182. line-height: 1.35;
  183. }
  184. /* 连接按钮 */
  185. .connect-btn {
  186. /* scale with device-item width */
  187. width: auto;
  188. padding: clamp(0.32rem, 0.9cqw, 0.5rem) clamp(0.5rem, 1.3cqw, 0.85rem);
  189. background: #1a1a1a;
  190. color: white;
  191. border: none;
  192. border-radius: clamp(6px, 1vw, 8px);
  193. cursor: pointer;
  194. font-size: clamp(0.65rem, 1.6cqw, 0.85rem);
  195. font-weight: 500;
  196. transition: all 0.2s ease;
  197. white-space: nowrap;
  198. margin-left: clamp(0.25rem, 1vw, 0.75rem);
  199. user-select: none;
  200. flex-shrink: 0;
  201. }
  202. .connect-btn:hover:not(.disabled) {
  203. background: #333;
  204. transform: translateY(-1px);
  205. }
  206. .connect-btn:active:not(.disabled) {
  207. transform: translateY(0);
  208. }
  209. .connect-btn.disabled {
  210. opacity: 0.4;
  211. cursor: not-allowed;
  212. background: #ccc;
  213. }
  214. .connect-btn.disabled:hover {
  215. transform: none;
  216. }
  217. /* 断开按钮 */
  218. .disconnect-btn {
  219. /* match connect button sizing */
  220. padding: clamp(0.32rem, 0.9cqw, 0.5rem) clamp(0.5rem, 1.3cqw, 0.85rem);
  221. background: #dc2626;
  222. color: white;
  223. border: none;
  224. border-radius: clamp(6px, 1vw, 8px);
  225. cursor: pointer;
  226. font-size: clamp(0.65rem, 1.6cqw, 0.85rem);
  227. font-weight: 500;
  228. transition: all 0.2s ease;
  229. white-space: nowrap;
  230. user-select: none;
  231. flex-shrink: 0;
  232. }
  233. .disconnect-btn:hover:not(.disabled) {
  234. background: #b91c1c;
  235. transform: translateY(-1px);
  236. }
  237. .disconnect-btn:active:not(.disabled) {
  238. transform: translateY(0);
  239. }
  240. .disconnect-btn.disabled {
  241. opacity: 0.4;
  242. cursor: not-allowed;
  243. background: #ccc;
  244. }
  245. .disconnect-btn.disabled:hover {
  246. transform: none;
  247. }
  248. /* 预览按钮 */
  249. .preview-btn {
  250. padding: clamp(0.32rem, 0.9cqw, 0.5rem) clamp(0.5rem, 1.3cqw, 0.85rem);
  251. background: #2abf6e;
  252. color: white;
  253. border: none;
  254. border-radius: clamp(6px, 1vw, 8px);
  255. cursor: pointer;
  256. font-size: clamp(0.65rem, 1.6cqw, 0.85rem);
  257. font-weight: 500;
  258. transition: all 0.2s ease;
  259. white-space: nowrap;
  260. user-select: none;
  261. flex-shrink: 0;
  262. }
  263. .preview-btn.disabled {
  264. opacity: 0.4;
  265. cursor: not-allowed;
  266. background: #ccc;
  267. }
  268. .preview-btn--active {
  269. background: #4a90e2;
  270. color: #fff;
  271. }
  272. /* 平板适配 */
  273. @media (min-width: 768px) and (max-width: 1023px) {
  274. .devices-header {
  275. padding: clamp(0.75rem, 1.5vw, 1rem);
  276. }
  277. }
  278. /* 移动端适配 */
  279. @media (max-width: 767px) {
  280. .Devices-container {
  281. padding: clamp(0.5rem, 2vw, 1rem);
  282. }
  283. .devices-header {
  284. flex-direction: column;
  285. align-items: flex-start;
  286. gap: clamp(0.5rem, 1.5vw, 0.75rem);
  287. padding: clamp(0.75rem, 2vw, 1rem);
  288. }
  289. .refresh-btn {
  290. width: 100%;
  291. justify-content: center;
  292. }
  293. .device-item {
  294. flex-direction: column;
  295. align-items: flex-start;
  296. gap: clamp(0.5rem, 1.5vw, 0.75rem);
  297. }
  298. .connect-btn {
  299. width: 100%;
  300. margin-left: 0;
  301. }
  302. }