index.css 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. }
  6. body {
  7. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  8. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  9. min-height: 100vh;
  10. padding: 20px;
  11. }
  12. .container {
  13. max-width: 1200px;
  14. margin: 0 auto;
  15. }
  16. .header {
  17. background: white;
  18. padding: 30px;
  19. border-radius: 10px;
  20. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  21. margin-bottom: 20px;
  22. display: flex;
  23. justify-content: space-between;
  24. align-items: center;
  25. }
  26. .header h1 {
  27. color: #333;
  28. font-size: 28px;
  29. }
  30. .btn {
  31. padding: 10px 20px;
  32. border: none;
  33. border-radius: 5px;
  34. cursor: pointer;
  35. font-size: 14px;
  36. transition: all 0.3s;
  37. font-weight: 500;
  38. }
  39. .btn-primary {
  40. background: #667eea;
  41. color: white;
  42. }
  43. .btn-primary:hover {
  44. background: #5568d3;
  45. transform: translateY(-2px);
  46. box-shadow: 0 4px 8px rgba(102, 126, 234, 0.3);
  47. }
  48. .btn-danger {
  49. background: #ef4444;
  50. color: white;
  51. }
  52. .btn-danger:hover {
  53. background: #dc2626;
  54. }
  55. .btn-secondary {
  56. background: #6b7280;
  57. color: white;
  58. }
  59. .btn-secondary:hover {
  60. background: #4b5563;
  61. }
  62. .card {
  63. background: white;
  64. border-radius: 10px;
  65. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  66. padding: 30px;
  67. margin-bottom: 20px;
  68. }
  69. .table-container {
  70. overflow-x: auto;
  71. }
  72. table {
  73. width: 100%;
  74. border-collapse: collapse;
  75. }
  76. th, td {
  77. padding: 12px;
  78. text-align: left;
  79. border-bottom: 1px solid #e5e7eb;
  80. }
  81. th {
  82. background: #f9fafb;
  83. font-weight: 600;
  84. color: #374151;
  85. }
  86. tr:hover {
  87. background: #f9fafb;
  88. }
  89. .badge {
  90. display: inline-block;
  91. padding: 4px 12px;
  92. border-radius: 12px;
  93. font-size: 12px;
  94. font-weight: 500;
  95. }
  96. .badge-success {
  97. background: #d1fae5;
  98. color: #065f46;
  99. }
  100. .badge-warning {
  101. background: #fef3c7;
  102. color: #92400e;
  103. }
  104. .modal {
  105. display: none;
  106. position: fixed;
  107. z-index: 1000;
  108. left: 0;
  109. top: 0;
  110. width: 100%;
  111. height: 100%;
  112. background: rgba(0, 0, 0, 0.5);
  113. animation: fadeIn 0.3s;
  114. }
  115. .modal.show {
  116. display: flex;
  117. align-items: center;
  118. justify-content: center;
  119. }
  120. @keyframes fadeIn {
  121. from { opacity: 0; }
  122. to { opacity: 1; }
  123. }
  124. .modal-content {
  125. background: white;
  126. border-radius: 10px;
  127. padding: 30px;
  128. width: 90%;
  129. max-width: 500px;
  130. animation: slideDown 0.3s;
  131. }
  132. @keyframes slideDown {
  133. from {
  134. transform: translateY(-50px);
  135. opacity: 0;
  136. }
  137. to {
  138. transform: translateY(0);
  139. opacity: 1;
  140. }
  141. }
  142. .modal-header {
  143. display: flex;
  144. justify-content: space-between;
  145. align-items: center;
  146. margin-bottom: 20px;
  147. }
  148. .modal-header h2 {
  149. color: #333;
  150. font-size: 24px;
  151. }
  152. .close {
  153. font-size: 28px;
  154. font-weight: bold;
  155. color: #999;
  156. cursor: pointer;
  157. border: none;
  158. background: none;
  159. }
  160. .close:hover {
  161. color: #333;
  162. }
  163. .form-group {
  164. margin-bottom: 20px;
  165. }
  166. .form-group label {
  167. display: block;
  168. margin-bottom: 8px;
  169. color: #374151;
  170. font-weight: 500;
  171. }
  172. .form-group input {
  173. width: 100%;
  174. padding: 10px;
  175. border: 1px solid #d1d5db;
  176. border-radius: 5px;
  177. font-size: 14px;
  178. }
  179. .form-group input:focus {
  180. outline: none;
  181. border-color: #667eea;
  182. box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
  183. }
  184. .form-actions {
  185. display: flex;
  186. gap: 10px;
  187. justify-content: flex-end;
  188. margin-top: 20px;
  189. }
  190. .pagination {
  191. display: flex;
  192. justify-content: center;
  193. align-items: center;
  194. gap: 10px;
  195. margin-top: 20px;
  196. }
  197. .pagination button {
  198. padding: 8px 16px;
  199. border: 1px solid #d1d5db;
  200. background: white;
  201. border-radius: 5px;
  202. cursor: pointer;
  203. }
  204. .pagination button:hover:not(:disabled) {
  205. background: #f9fafb;
  206. }
  207. .pagination button:disabled {
  208. opacity: 0.5;
  209. cursor: not-allowed;
  210. }
  211. .pagination .page-info {
  212. color: #6b7280;
  213. }
  214. .loading {
  215. text-align: center;
  216. padding: 40px;
  217. color: #6b7280;
  218. }
  219. .empty-state {
  220. text-align: center;
  221. padding: 60px 20px;
  222. color: #6b7280;
  223. }
  224. .empty-state svg {
  225. width: 100px;
  226. height: 100px;
  227. margin-bottom: 20px;
  228. opacity: 0.5;
  229. }
  230. .device-list {
  231. font-size: 12px;
  232. color: #6b7280;
  233. max-width: 200px;
  234. overflow: hidden;
  235. text-overflow: ellipsis;
  236. white-space: nowrap;
  237. }
  238. .device-detail-cell {
  239. cursor: pointer;
  240. color: #667eea;
  241. font-size: 14px;
  242. padding: 8px 12px;
  243. border-radius: 5px;
  244. transition: all 0.2s;
  245. max-width: 300px;
  246. }
  247. .device-detail-cell:hover {
  248. background: #f3f4f6;
  249. color: #5568d3;
  250. }
  251. .device-detail-cell .device-count {
  252. font-weight: 600;
  253. color: #667eea;
  254. }
  255. .device-detail-cell .device-preview {
  256. font-size: 12px;
  257. color: #6b7280;
  258. margin-top: 4px;
  259. }
  260. /* 设备列表弹框样式 */
  261. .device-list-modal .modal-content {
  262. max-width: 700px;
  263. }
  264. .device-list-table {
  265. width: 100%;
  266. border-collapse: collapse;
  267. margin-top: 20px;
  268. }
  269. .device-list-table th,
  270. .device-list-table td {
  271. padding: 12px;
  272. text-align: left;
  273. border-bottom: 1px solid #e5e7eb;
  274. }
  275. .device-list-table th {
  276. background: #f9fafb;
  277. font-weight: 600;
  278. color: #374151;
  279. }
  280. .device-list-table tr:hover {
  281. background: #f9fafb;
  282. }
  283. .device-list-empty {
  284. text-align: center;
  285. padding: 40px;
  286. color: #6b7280;
  287. }
  288. .actions {
  289. display: flex;
  290. gap: 8px;
  291. }
  292. .btn-sm {
  293. padding: 6px 12px;
  294. font-size: 12px;
  295. }
  296. .license-key-cell {
  297. display: flex;
  298. align-items: center;
  299. gap: 8px;
  300. max-width: 200px;
  301. }
  302. .license-key-text {
  303. flex: 1;
  304. overflow: hidden;
  305. text-overflow: ellipsis;
  306. white-space: nowrap;
  307. font-weight: 600;
  308. }
  309. .copy-btn {
  310. padding: 6px 12px;
  311. font-size: 12px;
  312. background: #667eea;
  313. color: white;
  314. border: none;
  315. border-radius: 5px;
  316. cursor: pointer;
  317. transition: all 0.2s;
  318. flex-shrink: 0;
  319. font-weight: 500;
  320. display: flex;
  321. align-items: center;
  322. gap: 4px;
  323. }
  324. .copy-btn:hover {
  325. background: #5568d3;
  326. transform: translateY(-1px);
  327. box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);
  328. }
  329. .copy-btn:active {
  330. transform: translateY(0);
  331. }
  332. /* Toast 通知样式 */
  333. .toast-container {
  334. position: fixed;
  335. top: 20px;
  336. right: 20px;
  337. z-index: 10000;
  338. display: flex;
  339. flex-direction: column;
  340. gap: 10px;
  341. }
  342. .toast {
  343. background: white;
  344. padding: 16px 20px;
  345. border-radius: 8px;
  346. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  347. display: flex;
  348. align-items: center;
  349. gap: 12px;
  350. min-width: 300px;
  351. max-width: 400px;
  352. animation: slideInRight 0.3s ease-out;
  353. position: relative;
  354. }
  355. @keyframes slideInRight {
  356. from {
  357. transform: translateX(100%);
  358. opacity: 0;
  359. }
  360. to {
  361. transform: translateX(0);
  362. opacity: 1;
  363. }
  364. }
  365. .toast.success {
  366. border-left: 4px solid #10b981;
  367. }
  368. .toast.error {
  369. border-left: 4px solid #ef4444;
  370. }
  371. .toast.warning {
  372. border-left: 4px solid #f59e0b;
  373. }
  374. .toast.info {
  375. border-left: 4px solid #3b82f6;
  376. }
  377. .toast-icon {
  378. font-size: 20px;
  379. flex-shrink: 0;
  380. }
  381. .toast.success .toast-icon {
  382. color: #10b981;
  383. }
  384. .toast.error .toast-icon {
  385. color: #ef4444;
  386. }
  387. .toast.warning .toast-icon {
  388. color: #f59e0b;
  389. }
  390. .toast.info .toast-icon {
  391. color: #3b82f6;
  392. }
  393. .toast-message {
  394. flex: 1;
  395. color: #374151;
  396. font-size: 14px;
  397. line-height: 1.5;
  398. }
  399. .toast-close {
  400. background: none;
  401. border: none;
  402. font-size: 18px;
  403. color: #9ca3af;
  404. cursor: pointer;
  405. padding: 0;
  406. width: 20px;
  407. height: 20px;
  408. display: flex;
  409. align-items: center;
  410. justify-content: center;
  411. flex-shrink: 0;
  412. }
  413. .toast-close:hover {
  414. color: #374151;
  415. }
  416. /* 确认对话框样式 */
  417. .confirm-dialog {
  418. display: none;
  419. position: fixed;
  420. z-index: 10001;
  421. left: 0;
  422. top: 0;
  423. width: 100%;
  424. height: 100%;
  425. background: rgba(0, 0, 0, 0.5);
  426. align-items: center;
  427. justify-content: center;
  428. animation: fadeIn 0.3s;
  429. }
  430. .confirm-dialog.show {
  431. display: flex;
  432. }
  433. .confirm-content {
  434. background: white;
  435. border-radius: 10px;
  436. padding: 30px;
  437. width: 90%;
  438. max-width: 400px;
  439. box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
  440. animation: slideDown 0.3s;
  441. }
  442. .confirm-icon {
  443. font-size: 48px;
  444. text-align: center;
  445. margin-bottom: 20px;
  446. }
  447. .confirm-title {
  448. font-size: 20px;
  449. font-weight: 600;
  450. color: #374151;
  451. text-align: center;
  452. margin-bottom: 15px;
  453. }
  454. .confirm-message {
  455. color: #6b7280;
  456. text-align: center;
  457. margin-bottom: 25px;
  458. line-height: 1.6;
  459. }
  460. .confirm-actions {
  461. display: flex;
  462. gap: 10px;
  463. justify-content: center;
  464. }
  465. .confirm-actions .btn {
  466. min-width: 100px;
  467. }
  468. /* 统计信息卡片样式 */
  469. .stats-container {
  470. display: grid;
  471. grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  472. gap: 20px;
  473. margin-bottom: 20px;
  474. }
  475. .stat-card {
  476. background: white;
  477. border-radius: 10px;
  478. padding: 20px;
  479. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  480. display: flex;
  481. flex-direction: column;
  482. }
  483. .stat-label {
  484. color: #6b7280;
  485. font-size: 14px;
  486. margin-bottom: 8px;
  487. }
  488. .stat-value {
  489. color: #111827;
  490. font-size: 28px;
  491. font-weight: 600;
  492. }
  493. .stat-card.primary .stat-value {
  494. color: #667eea;
  495. }
  496. .stat-card.success .stat-value {
  497. color: #10b981;
  498. }
  499. .stat-card.warning .stat-value {
  500. color: #f59e0b;
  501. }
  502. .stat-card.danger .stat-value {
  503. color: #ef4444;
  504. }
  505. /* 筛选和操作栏样式 */
  506. .filter-bar {
  507. display: flex;
  508. justify-content: space-between;
  509. align-items: center;
  510. margin-bottom: 20px;
  511. flex-wrap: wrap;
  512. gap: 15px;
  513. }
  514. .filter-group {
  515. display: flex;
  516. align-items: center;
  517. gap: 10px;
  518. }
  519. .filter-group label {
  520. color: #374151;
  521. font-weight: 500;
  522. font-size: 14px;
  523. }
  524. .filter-select {
  525. padding: 8px 12px;
  526. border: 1px solid #d1d5db;
  527. border-radius: 5px;
  528. font-size: 14px;
  529. background: white;
  530. cursor: pointer;
  531. min-width: 120px;
  532. }
  533. .filter-select:focus {
  534. outline: none;
  535. border-color: #667eea;
  536. box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
  537. }