drag-upload-modal.component.scss 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735
  1. // 拖拽上传弹窗样式
  2. .drag-upload-modal-overlay {
  3. position: fixed;
  4. top: 0;
  5. left: 0;
  6. right: 0;
  7. bottom: 0;
  8. background: rgba(0, 0, 0, 0.6);
  9. display: flex;
  10. align-items: center;
  11. justify-content: center;
  12. z-index: 2000;
  13. backdrop-filter: blur(4px);
  14. animation: fadeIn 0.3s ease-out;
  15. }
  16. .drag-upload-modal-container {
  17. background: white;
  18. border-radius: 16px;
  19. width: 90vw;
  20. max-width: 800px;
  21. max-height: 85vh;
  22. display: flex;
  23. flex-direction: column;
  24. box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  25. animation: slideUp 0.3s ease-out;
  26. overflow: hidden;
  27. }
  28. // 弹窗头部
  29. .modal-header {
  30. padding: 24px 32px;
  31. border-bottom: 1px solid #f0f0f0;
  32. display: flex;
  33. align-items: center;
  34. justify-content: space-between;
  35. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  36. color: white;
  37. .header-info {
  38. h3 {
  39. margin: 0 0 8px 0;
  40. font-size: 20px;
  41. font-weight: 600;
  42. }
  43. .upload-target-info {
  44. display: flex;
  45. align-items: center;
  46. gap: 8px;
  47. font-size: 13px;
  48. opacity: 0.9;
  49. .info-text {
  50. font-weight: 400;
  51. }
  52. }
  53. }
  54. .close-btn {
  55. background: none;
  56. border: none;
  57. color: white;
  58. cursor: pointer;
  59. padding: 8px;
  60. border-radius: 8px;
  61. transition: background-color 0.2s ease;
  62. &:hover {
  63. background: rgba(255, 255, 255, 0.1);
  64. }
  65. svg {
  66. display: block;
  67. }
  68. }
  69. }
  70. // 弹窗主体
  71. .modal-body {
  72. flex: 1;
  73. padding: 24px 32px;
  74. overflow-y: auto;
  75. max-height: calc(85vh - 200px);
  76. background: #f8f9fa;
  77. }
  78. // 表格容器
  79. .files-table-container {
  80. background: white;
  81. border-radius: 12px;
  82. overflow: hidden;
  83. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  84. border: 2px solid #40e0d0;
  85. }
  86. // 表格样式
  87. .files-table {
  88. width: 100%;
  89. border-collapse: collapse;
  90. font-size: 14px;
  91. // 表头
  92. thead {
  93. background: linear-gradient(135deg, #40e0d0 0%, #48d1cc 100%);
  94. color: white;
  95. tr {
  96. th {
  97. padding: 16px 12px;
  98. text-align: left;
  99. font-weight: 600;
  100. font-size: 15px;
  101. border-bottom: 3px solid #36d0c0;
  102. &.col-file {
  103. width: 120px;
  104. text-align: center;
  105. }
  106. &.col-name {
  107. width: 25%;
  108. }
  109. &.col-upload {
  110. width: 20%;
  111. text-align: center;
  112. }
  113. &.col-space {
  114. width: 20%;
  115. text-align: center;
  116. }
  117. &.col-stage {
  118. width: 20%;
  119. text-align: center;
  120. }
  121. }
  122. }
  123. }
  124. // 表体
  125. tbody {
  126. .empty-row {
  127. .empty-cell {
  128. padding: 60px 20px;
  129. text-align: center;
  130. .empty-state {
  131. display: flex;
  132. flex-direction: column;
  133. align-items: center;
  134. gap: 16px;
  135. .empty-icon {
  136. opacity: 0.3;
  137. }
  138. p {
  139. margin: 0;
  140. color: #999;
  141. font-size: 15px;
  142. }
  143. }
  144. }
  145. }
  146. .file-row {
  147. border-bottom: 1px solid #e8e8e8;
  148. transition: all 0.2s;
  149. &:hover {
  150. background: #f5f5f5;
  151. }
  152. &.uploading {
  153. background: #e6f7ff;
  154. }
  155. &.success {
  156. background: #f6ffed;
  157. }
  158. &.error {
  159. background: #fff1f0;
  160. }
  161. td {
  162. padding: 16px 12px;
  163. vertical-align: middle;
  164. }
  165. // 文件列
  166. .col-file {
  167. text-align: center;
  168. .file-preview-wrapper {
  169. position: relative;
  170. display: inline-block;
  171. .file-preview {
  172. width: 80px;
  173. height: 80px;
  174. border-radius: 8px;
  175. overflow: hidden;
  176. background: #f5f5f5;
  177. display: flex;
  178. align-items: center;
  179. justify-content: center;
  180. border: 2px solid #e8e8e8;
  181. img {
  182. width: 100%;
  183. height: 100%;
  184. object-fit: cover;
  185. }
  186. .file-icon {
  187. color: #999;
  188. }
  189. }
  190. .delete-btn {
  191. position: absolute;
  192. top: -8px;
  193. right: -8px;
  194. width: 28px;
  195. height: 28px;
  196. border-radius: 50%;
  197. background: #ff4d4f;
  198. border: 2px solid white;
  199. color: white;
  200. display: flex;
  201. align-items: center;
  202. justify-content: center;
  203. cursor: pointer;
  204. transition: all 0.2s;
  205. box-shadow: 0 2px 6px rgba(255, 77, 79, 0.4);
  206. &:hover:not(:disabled) {
  207. background: #ff7875;
  208. transform: scale(1.1);
  209. }
  210. &:disabled {
  211. opacity: 0.5;
  212. cursor: not-allowed;
  213. }
  214. }
  215. }
  216. }
  217. // 名称列
  218. .col-name {
  219. .file-name-wrapper {
  220. .file-name {
  221. font-weight: 500;
  222. color: #333;
  223. margin-bottom: 6px;
  224. overflow: hidden;
  225. text-overflow: ellipsis;
  226. white-space: nowrap;
  227. }
  228. .file-size {
  229. font-size: 12px;
  230. color: #999;
  231. }
  232. }
  233. }
  234. // 上传列
  235. .col-upload {
  236. text-align: center;
  237. .upload-status-wrapper {
  238. display: flex;
  239. flex-direction: column;
  240. align-items: center;
  241. gap: 4px;
  242. .status-text {
  243. font-size: 13px;
  244. font-weight: 500;
  245. padding: 4px 12px;
  246. border-radius: 12px;
  247. white-space: nowrap;
  248. &.analyzing {
  249. color: #1890ff;
  250. background: #e6f7ff;
  251. }
  252. &.success {
  253. color: #52c41a;
  254. background: #f6ffed;
  255. }
  256. &.error {
  257. color: #ff4d4f;
  258. background: #fff1f0;
  259. }
  260. &.pending {
  261. color: #faad14;
  262. background: #fff7e6;
  263. }
  264. }
  265. .upload-progress-inline {
  266. width: 100%;
  267. display: flex;
  268. flex-direction: column;
  269. align-items: center;
  270. gap: 4px;
  271. .progress-bar-inline {
  272. width: 100%;
  273. height: 6px;
  274. background: #f0f0f0;
  275. border-radius: 3px;
  276. overflow: hidden;
  277. .progress-fill-inline {
  278. height: 100%;
  279. background: linear-gradient(90deg, #1890ff, #40a9ff);
  280. border-radius: 3px;
  281. transition: width 0.3s ease;
  282. }
  283. }
  284. .progress-text-inline {
  285. font-size: 12px;
  286. color: #1890ff;
  287. font-weight: 600;
  288. }
  289. }
  290. }
  291. }
  292. // 空间列和阶段列
  293. .col-space,
  294. .col-stage {
  295. text-align: center;
  296. .table-select {
  297. width: 100%;
  298. max-width: 150px;
  299. padding: 8px 12px;
  300. border: 2px solid #d9d9d9;
  301. border-radius: 8px;
  302. font-size: 13px;
  303. color: #333;
  304. background: white;
  305. cursor: pointer;
  306. transition: all 0.2s;
  307. font-weight: 500;
  308. &:hover:not(:disabled) {
  309. border-color: #40a9ff;
  310. }
  311. &:focus {
  312. outline: none;
  313. border-color: #1890ff;
  314. box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
  315. }
  316. &.ai-suggested {
  317. border-color: #52c41a;
  318. background: linear-gradient(135deg, #f6ffed 0%, white 100%);
  319. box-shadow: 0 0 0 2px rgba(82, 196, 26, 0.1);
  320. }
  321. &:disabled {
  322. background: #f5f5f5;
  323. color: #bfbfbf;
  324. cursor: not-allowed;
  325. border-color: #e8e8e8;
  326. }
  327. option {
  328. padding: 8px;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. // 上传警告
  336. .upload-warning {
  337. display: flex;
  338. align-items: center;
  339. gap: 8px;
  340. padding: 12px 16px;
  341. margin-top: 16px;
  342. background: #fff7e6;
  343. border: 2px solid #ffd591;
  344. border-radius: 8px;
  345. color: #d46b08;
  346. font-size: 13px;
  347. font-weight: 500;
  348. svg {
  349. flex-shrink: 0;
  350. color: #faad14;
  351. }
  352. }
  353. // 弹窗底部
  354. .modal-footer {
  355. padding: 20px 32px;
  356. border-top: 2px solid #e8e8e8;
  357. display: flex;
  358. align-items: center;
  359. justify-content: flex-end;
  360. gap: 12px;
  361. background: white;
  362. .cancel-btn,
  363. .confirm-btn {
  364. padding: 12px 24px;
  365. border-radius: 8px;
  366. font-size: 14px;
  367. font-weight: 600;
  368. cursor: pointer;
  369. transition: all 0.2s;
  370. border: none;
  371. }
  372. .cancel-btn {
  373. background: #f5f5f5;
  374. color: #595959;
  375. &:hover {
  376. background: #e6e6e6;
  377. }
  378. }
  379. .confirm-btn {
  380. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  381. color: white;
  382. box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
  383. &:hover:not(:disabled) {
  384. transform: translateY(-1px);
  385. box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
  386. }
  387. &:disabled {
  388. background: #d9d9d9;
  389. color: #bfbfbf;
  390. cursor: not-allowed;
  391. transform: none;
  392. box-shadow: none;
  393. }
  394. }
  395. }
  396. // AI分析横幅
  397. .analysis-banner {
  398. display: flex;
  399. align-items: center;
  400. gap: 12px;
  401. padding: 16px 20px;
  402. margin-bottom: 20px;
  403. background: linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%);
  404. border: 2px solid #91d5ff;
  405. border-radius: 12px;
  406. animation: slideDown 0.3s ease-out;
  407. &.success {
  408. background: linear-gradient(135deg, #f6ffed 0%, #f0fff4 100%);
  409. border-color: #b7eb8f;
  410. .banner-icon svg {
  411. color: #52c41a;
  412. }
  413. .banner-title {
  414. color: #389e0d;
  415. }
  416. }
  417. .banner-icon {
  418. flex-shrink: 0;
  419. width: 40px;
  420. height: 40px;
  421. display: flex;
  422. align-items: center;
  423. justify-content: center;
  424. background: white;
  425. border-radius: 50%;
  426. box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);
  427. svg {
  428. color: #1890ff;
  429. &.rotating {
  430. animation: rotate 2s linear infinite;
  431. }
  432. }
  433. }
  434. .banner-content {
  435. flex: 1;
  436. .banner-title {
  437. font-size: 15px;
  438. font-weight: 600;
  439. color: #1890ff;
  440. margin-bottom: 4px;
  441. }
  442. .banner-text {
  443. font-size: 13px;
  444. color: #595959;
  445. line-height: 1.4;
  446. }
  447. }
  448. }
  449. // AI分析进度覆盖层
  450. .analysis-progress-overlay {
  451. position: absolute;
  452. top: 0;
  453. left: 0;
  454. right: 0;
  455. bottom: 0;
  456. background: rgba(255, 255, 255, 0.98);
  457. backdrop-filter: blur(8px);
  458. display: flex;
  459. align-items: center;
  460. justify-content: center;
  461. z-index: 100;
  462. border-radius: 16px;
  463. .progress-content {
  464. text-align: center;
  465. padding: 40px;
  466. max-width: 400px;
  467. .ai-brain-icon {
  468. margin: 0 auto 24px;
  469. width: 64px;
  470. height: 64px;
  471. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  472. border-radius: 50%;
  473. display: flex;
  474. align-items: center;
  475. justify-content: center;
  476. animation: pulse 2s ease-in-out infinite;
  477. box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
  478. svg {
  479. color: white;
  480. width: 32px;
  481. height: 32px;
  482. }
  483. }
  484. .progress-text {
  485. font-size: 18px;
  486. font-weight: 600;
  487. color: #475569;
  488. line-height: 1.5;
  489. margin-bottom: 20px;
  490. }
  491. .progress-bar {
  492. width: 100%;
  493. height: 6px;
  494. background: #e2e8f0;
  495. border-radius: 3px;
  496. overflow: hidden;
  497. margin-top: 16px;
  498. .progress-fill {
  499. height: 100%;
  500. background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
  501. border-radius: 3px;
  502. transition: width 0.3s ease;
  503. animation: shimmer 2s linear infinite;
  504. }
  505. }
  506. }
  507. @keyframes shimmer {
  508. 0% {
  509. background-position: -200% 0;
  510. }
  511. 100% {
  512. background-position: 200% 0;
  513. }
  514. }
  515. }
  516. // 简化的文件分析表格
  517. .files-analysis-table {
  518. .analysis-table {
  519. width: 100%;
  520. border-collapse: collapse;
  521. background: white;
  522. border-radius: 8px;
  523. overflow: hidden;
  524. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  525. thead {
  526. background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
  527. th {
  528. padding: 16px 12px;
  529. text-align: left;
  530. font-weight: 600;
  531. color: #262626;
  532. font-size: 14px;
  533. border-bottom: 2px solid #e6f7ff;
  534. &.col-file { width: 80px; }
  535. &.col-name { width: 200px; }
  536. &.col-upload { width: 100px; }
  537. &.col-space { width: 120px; }
  538. &.col-stage { width: 120px; }
  539. }
  540. }
  541. tbody {
  542. .file-row {
  543. transition: all 0.2s ease;
  544. border-bottom: 1px solid #f0f0f0;
  545. &:hover {
  546. background: #fafafa;
  547. }
  548. &.analyzing {
  549. background: linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%);
  550. }
  551. &.completed {
  552. background: linear-gradient(135deg, #f6ffed 0%, #f0fff4 100%);
  553. }
  554. td {
  555. padding: 12px;
  556. vertical-align: middle;
  557. }
  558. // 文件预览列
  559. .file-preview-container {
  560. position: relative;
  561. display: flex;
  562. align-items: center;
  563. .file-thumbnail {
  564. width: 50px;
  565. height: 50px;
  566. object-fit: cover;
  567. border-radius: 6px;
  568. border: 2px solid #f0f0f0;
  569. }
  570. .file-icon-placeholder {
  571. width: 50px;
  572. height: 50px;
  573. display: flex;
  574. align-items: center;
  575. justify-content: center;
  576. background: #f5f5f5;
  577. border-radius: 6px;
  578. border: 2px solid #f0f0f0;
  579. svg {
  580. color: #8c8c8c;
  581. }
  582. }
  583. .file-delete-btn {
  584. position: absolute;
  585. top: -8px;
  586. right: -8px;
  587. width: 24px;
  588. height: 24px;
  589. background: #ff4d4f;
  590. border: 2px solid white;
  591. border-radius: 50%;
  592. display: flex;
  593. align-items: center;
  594. justify-content: center;
  595. cursor: pointer;
  596. transition: all 0.2s ease;
  597. &:hover {
  598. background: #ff7875;
  599. transform: scale(1.1);
  600. }
  601. svg {
  602. color: white;
  603. }
  604. }
  605. }
  606. // 文件信息列
  607. .file-info {
  608. .file-name {
  609. font-size: 13px;
  610. font-weight: 600;
  611. color: #262626;
  612. margin-bottom: 4px;
  613. overflow: hidden;
  614. text-overflow: ellipsis;
  615. white-space: nowrap;
  616. }
  617. .file-size {
  618. font-size: 11px;
  619. color: #8c8c8c;
  620. }
  621. }
  622. // 上传状态列
  623. .upload-status {
  624. .status {
  625. padding: 4px 8px;
  626. border-radius: 4px;
  627. font-size: 12px;
  628. font-weight: 600;
  629. &.analyzing {
  630. background: #e6f7ff;
  631. color: #1890ff;
  632. }
  633. &.completed {
  634. background: #f6ffed;
  635. color: #52c41a;
  636. }
  637. &.pending {
  638. background: #fff7e6;
  639. color: #faad14;
  640. }
  641. }
  642. }
  643. // 空间和阶段结果列
  644. .space-result,
  645. .stage-result {
  646. .placeholder {
  647. color: #94a3b8;
  648. font-size: 12px;
  649. font-style: italic;
  650. &.analyzing {
  651. color: #667eea;
  652. font-weight: 600;
  653. animation: pulse 1.5s ease-in-out infinite;
  654. }
  655. }
  656. .ai-result-container {
  657. display: flex;
  658. align-items: center;
  659. justify-content: center;
  660. gap: 8px;
  661. flex-wrap: wrap;
  662. }
  663. .ai-result {
  664. color: #059669;
  665. font-weight: 600;
  666. background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
  667. padding: 6px 12px;
  668. border-radius: 12px;
  669. border: 1px solid #6ee7b7;
  670. display: inline-block;
  671. font-size: 13px;
  672. &.stage-tag {
  673. &[data-stage="white_model"] {
  674. background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
  675. color: #475569;
  676. border-color: #cbd5e1;
  677. }
  678. &[data-stage="soft_decor"] {
  679. background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
  680. color: #92400e;
  681. border-color: #f59e0b;
  682. }
  683. &[data-stage="rendering"] {
  684. background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
  685. color: #1e40af;
  686. border-color: #3b82f6;
  687. }
  688. &[data-stage="post_process"] {
  689. background: linear-gradient(135deg, #f3e8ff 0%, #e9d5ff 100%);
  690. color: #7c3aed;
  691. border-color: #a855f7;
  692. }
  693. }
  694. }
  695. .confidence-badge,
  696. .quality-badge {
  697. font-size: 11px;
  698. font-weight: 700;
  699. color: white;
  700. padding: 2px 6px;
  701. border-radius: 8px;
  702. display: inline-block;
  703. text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  704. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  705. }
  706. }
  707. }
  708. }
  709. }
  710. }
  711. // JSON格式预览区域 (保留但隐藏)
  712. .json-preview-section {
  713. display: none; // 暂时隐藏JSON预览
  714. margin-bottom: 24px;
  715. background: linear-gradient(135deg, #fff7e6 0%, #fffbf0 100%);
  716. border: 2px solid #ffd591;
  717. border-radius: 12px;
  718. overflow: hidden;
  719. animation: slideDown 0.3s ease-out;
  720. .json-preview-header {
  721. display: flex;
  722. align-items: center;
  723. justify-content: space-between;
  724. padding: 16px 20px;
  725. background: linear-gradient(135deg, #faad14 0%, #d48806 100%);
  726. color: white;
  727. .header-left {
  728. display: flex;
  729. align-items: center;
  730. gap: 8px;
  731. font-size: 15px;
  732. font-weight: 600;
  733. svg {
  734. flex-shrink: 0;
  735. }
  736. }
  737. .toggle-json-btn {
  738. background: rgba(255, 255, 255, 0.2);
  739. border: 1px solid rgba(255, 255, 255, 0.3);
  740. color: white;
  741. padding: 6px 12px;
  742. border-radius: 6px;
  743. font-size: 12px;
  744. font-weight: 500;
  745. cursor: pointer;
  746. transition: all 0.2s ease;
  747. &:hover {
  748. background: rgba(255, 255, 255, 0.3);
  749. }
  750. }
  751. }
  752. .json-preview-content {
  753. padding: 20px;
  754. background: white;
  755. .json-grid {
  756. display: grid;
  757. grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  758. gap: 16px;
  759. .json-item {
  760. background: #fafafa;
  761. border: 2px solid #f0f0f0;
  762. border-radius: 8px;
  763. overflow: hidden;
  764. transition: all 0.2s ease;
  765. &.analyzing {
  766. border-color: #91d5ff;
  767. background: linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%);
  768. }
  769. &:hover {
  770. border-color: #40a9ff;
  771. box-shadow: 0 4px 12px rgba(64, 169, 255, 0.15);
  772. }
  773. .json-item-header {
  774. display: flex;
  775. align-items: center;
  776. justify-content: space-between;
  777. padding: 12px 16px;
  778. background: white;
  779. border-bottom: 1px solid #f0f0f0;
  780. .file-info {
  781. flex: 1;
  782. min-width: 0;
  783. .file-name {
  784. display: block;
  785. font-size: 13px;
  786. font-weight: 600;
  787. color: #262626;
  788. overflow: hidden;
  789. text-overflow: ellipsis;
  790. white-space: nowrap;
  791. margin-bottom: 2px;
  792. }
  793. .file-size {
  794. font-size: 11px;
  795. color: #8c8c8c;
  796. }
  797. }
  798. .status-badge {
  799. padding: 4px 8px;
  800. background: #faad14;
  801. color: white;
  802. border-radius: 4px;
  803. font-size: 11px;
  804. font-weight: 600;
  805. white-space: nowrap;
  806. &.completed {
  807. background: #52c41a;
  808. }
  809. }
  810. }
  811. .json-item-body {
  812. padding: 16px;
  813. .preview-image {
  814. width: 100%;
  815. height: 120px;
  816. border-radius: 6px;
  817. overflow: hidden;
  818. margin-bottom: 12px;
  819. background: #f5f5f5;
  820. img {
  821. width: 100%;
  822. height: 100%;
  823. object-fit: cover;
  824. }
  825. }
  826. .analysis-info {
  827. .info-row {
  828. display: flex;
  829. align-items: center;
  830. justify-content: space-between;
  831. margin-bottom: 8px;
  832. font-size: 12px;
  833. &:last-child {
  834. margin-bottom: 0;
  835. }
  836. .label {
  837. color: #595959;
  838. font-weight: 500;
  839. min-width: 50px;
  840. }
  841. .value {
  842. color: #262626;
  843. font-weight: 600;
  844. text-align: right;
  845. &.confidence {
  846. color: #faad14;
  847. &.high {
  848. color: #52c41a;
  849. }
  850. }
  851. }
  852. }
  853. }
  854. }
  855. }
  856. }
  857. }
  858. }
  859. // 文件区域
  860. .files-section {
  861. .section-header {
  862. display: flex;
  863. align-items: center;
  864. justify-content: space-between;
  865. margin-bottom: 20px;
  866. h4 {
  867. margin: 0;
  868. font-size: 16px;
  869. font-weight: 600;
  870. color: #262626;
  871. }
  872. .file-actions {
  873. .add-files-btn {
  874. display: flex;
  875. align-items: center;
  876. gap: 6px;
  877. padding: 8px 16px;
  878. background: #f8f9fa;
  879. border: 1px solid #e9ecef;
  880. border-radius: 8px;
  881. color: #495057;
  882. font-size: 14px;
  883. cursor: pointer;
  884. transition: all 0.2s ease;
  885. &:hover {
  886. background: #e9ecef;
  887. border-color: #dee2e6;
  888. }
  889. svg {
  890. flex-shrink: 0;
  891. }
  892. }
  893. }
  894. }
  895. }
  896. // 文件列表
  897. .files-list {
  898. border: 1px solid #e9ecef;
  899. border-radius: 12px;
  900. background: #fafbfc;
  901. min-height: 200px;
  902. max-height: 400px;
  903. overflow-y: auto;
  904. .empty-files {
  905. display: flex;
  906. flex-direction: column;
  907. align-items: center;
  908. justify-content: center;
  909. height: 200px;
  910. color: #8c8c8c;
  911. .empty-icon {
  912. font-size: 48px;
  913. margin-bottom: 12px;
  914. opacity: 0.6;
  915. }
  916. p {
  917. margin: 0;
  918. font-size: 14px;
  919. }
  920. }
  921. }
  922. // 文件项
  923. .file-item {
  924. display: flex;
  925. align-items: center;
  926. gap: 16px;
  927. padding: 16px;
  928. border-bottom: 1px solid #f0f0f0;
  929. transition: background-color 0.2s ease;
  930. &:last-child {
  931. border-bottom: none;
  932. }
  933. &:hover {
  934. background: rgba(24, 144, 255, 0.04);
  935. }
  936. &.uploading {
  937. background: rgba(24, 144, 255, 0.08);
  938. }
  939. &.error {
  940. background: rgba(255, 77, 79, 0.08);
  941. }
  942. // 文件预览
  943. .file-preview {
  944. position: relative;
  945. width: 64px;
  946. height: 64px;
  947. border-radius: 8px;
  948. overflow: hidden;
  949. background: #f5f5f5;
  950. display: flex;
  951. align-items: center;
  952. justify-content: center;
  953. flex-shrink: 0;
  954. .preview-image {
  955. width: 100%;
  956. height: 100%;
  957. object-fit: cover;
  958. }
  959. .file-icon {
  960. font-size: 24px;
  961. }
  962. // 状态覆盖层
  963. .upload-overlay,
  964. .success-overlay,
  965. .error-overlay {
  966. position: absolute;
  967. top: 0;
  968. left: 0;
  969. right: 0;
  970. bottom: 0;
  971. display: flex;
  972. align-items: center;
  973. justify-content: center;
  974. border-radius: 8px;
  975. }
  976. .upload-overlay {
  977. background: rgba(24, 144, 255, 0.9);
  978. .progress-circle {
  979. position: relative;
  980. display: flex;
  981. align-items: center;
  982. justify-content: center;
  983. .progress-text {
  984. position: absolute;
  985. color: white;
  986. font-size: 10px;
  987. font-weight: 600;
  988. }
  989. }
  990. }
  991. .success-overlay {
  992. background: rgba(82, 196, 26, 0.9);
  993. .success-icon {
  994. color: white;
  995. font-size: 20px;
  996. font-weight: bold;
  997. }
  998. }
  999. .error-overlay {
  1000. background: rgba(255, 77, 79, 0.9);
  1001. .error-icon {
  1002. color: white;
  1003. font-size: 20px;
  1004. font-weight: bold;
  1005. }
  1006. }
  1007. }
  1008. // 文件信息
  1009. .file-info {
  1010. flex: 1;
  1011. min-width: 0;
  1012. .file-name {
  1013. font-size: 14px;
  1014. font-weight: 500;
  1015. color: #262626;
  1016. margin-bottom: 4px;
  1017. overflow: hidden;
  1018. text-overflow: ellipsis;
  1019. white-space: nowrap;
  1020. }
  1021. .file-details {
  1022. display: flex;
  1023. align-items: center;
  1024. gap: 12px;
  1025. font-size: 12px;
  1026. color: #8c8c8c;
  1027. .error-message {
  1028. color: #ff4d4f;
  1029. font-weight: 500;
  1030. }
  1031. .analyzing-message {
  1032. color: #1890ff;
  1033. font-weight: 500;
  1034. animation: pulse 1.5s ease-in-out infinite;
  1035. }
  1036. }
  1037. // 🔥 图片分析结果样式(简化版)
  1038. .analysis-result {
  1039. margin-top: 8px;
  1040. padding: 8px 10px;
  1041. background: linear-gradient(135deg, #f6ffed 0%, #f0fff4 100%);
  1042. border: 1px solid #b7eb8f;
  1043. border-radius: 6px;
  1044. font-size: 11px;
  1045. .analysis-row {
  1046. display: flex;
  1047. align-items: center;
  1048. gap: 6px;
  1049. margin-bottom: 4px;
  1050. &:last-child {
  1051. margin-bottom: 0;
  1052. }
  1053. }
  1054. .analysis-label {
  1055. color: #52c41a;
  1056. font-weight: 600;
  1057. min-width: 50px;
  1058. }
  1059. .analysis-value {
  1060. color: #262626;
  1061. font-weight: 500;
  1062. }
  1063. .confidence-badge {
  1064. padding: 2px 6px;
  1065. background: #faad14;
  1066. color: white;
  1067. border-radius: 3px;
  1068. font-size: 10px;
  1069. font-weight: 600;
  1070. &.high {
  1071. background: #52c41a;
  1072. }
  1073. }
  1074. .quality-badge {
  1075. color: white;
  1076. padding: 2px 6px;
  1077. border-radius: 3px;
  1078. font-size: 10px;
  1079. font-weight: 600;
  1080. text-transform: uppercase;
  1081. }
  1082. }
  1083. // 🔥 文件分类选择样式
  1084. .file-classification {
  1085. margin-top: 12px;
  1086. padding: 12px;
  1087. background: linear-gradient(135deg, #fff7e6 0%, #fffbf0 100%);
  1088. border: 2px solid #ffd591;
  1089. border-radius: 8px;
  1090. .classification-row {
  1091. display: flex;
  1092. align-items: center;
  1093. gap: 8px;
  1094. margin-bottom: 8px;
  1095. &:last-child {
  1096. margin-bottom: 0;
  1097. }
  1098. }
  1099. .classification-label {
  1100. font-size: 12px;
  1101. font-weight: 600;
  1102. color: #d46b08;
  1103. min-width: 45px;
  1104. }
  1105. .classification-select {
  1106. flex: 1;
  1107. padding: 6px 10px;
  1108. border: 1px solid #d9d9d9;
  1109. border-radius: 6px;
  1110. font-size: 12px;
  1111. color: #262626;
  1112. background: white;
  1113. cursor: pointer;
  1114. transition: all 0.2s ease;
  1115. &:hover {
  1116. border-color: #40a9ff;
  1117. }
  1118. &:focus {
  1119. outline: none;
  1120. border-color: #1890ff;
  1121. box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
  1122. }
  1123. &.ai-suggested {
  1124. border-color: #52c41a;
  1125. background: linear-gradient(135deg, #f6ffed 0%, white 100%);
  1126. }
  1127. option {
  1128. padding: 8px;
  1129. }
  1130. }
  1131. }
  1132. }
  1133. // 文件操作
  1134. .file-actions {
  1135. .remove-btn {
  1136. background: none;
  1137. border: none;
  1138. color: #8c8c8c;
  1139. cursor: pointer;
  1140. padding: 8px;
  1141. border-radius: 6px;
  1142. transition: all 0.2s ease;
  1143. &:hover {
  1144. background: #fff2f0;
  1145. color: #ff4d4f;
  1146. }
  1147. }
  1148. }
  1149. }
  1150. // 🔥 AI分析进度样式
  1151. .analysis-progress {
  1152. margin-top: 20px;
  1153. padding: 16px;
  1154. background: linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%);
  1155. border: 1px solid #91d5ff;
  1156. border-radius: 8px;
  1157. .progress-header {
  1158. display: flex;
  1159. align-items: center;
  1160. gap: 8px;
  1161. margin-bottom: 12px;
  1162. color: #1890ff;
  1163. font-weight: 600;
  1164. font-size: 14px;
  1165. svg {
  1166. flex-shrink: 0;
  1167. animation: rotate 2s linear infinite;
  1168. }
  1169. }
  1170. .progress-text {
  1171. color: #1890ff;
  1172. font-size: 13px;
  1173. margin-bottom: 8px;
  1174. font-weight: 500;
  1175. }
  1176. .progress-bar {
  1177. height: 4px;
  1178. background: #e6f7ff;
  1179. border-radius: 2px;
  1180. overflow: hidden;
  1181. .progress-fill {
  1182. height: 100%;
  1183. background: linear-gradient(90deg, #1890ff, #40a9ff);
  1184. border-radius: 2px;
  1185. animation: progressMove 2s ease-in-out infinite;
  1186. }
  1187. }
  1188. }
  1189. // 上传提示
  1190. .upload-tips {
  1191. margin-top: 24px;
  1192. padding: 16px;
  1193. background: #f6ffed;
  1194. border: 1px solid #b7eb8f;
  1195. border-radius: 8px;
  1196. .tips-header {
  1197. display: flex;
  1198. align-items: center;
  1199. gap: 8px;
  1200. margin-bottom: 12px;
  1201. color: #389e0d;
  1202. font-weight: 500;
  1203. font-size: 14px;
  1204. svg {
  1205. flex-shrink: 0;
  1206. }
  1207. }
  1208. .tips-list {
  1209. margin: 0;
  1210. padding-left: 20px;
  1211. color: #52c41a;
  1212. font-size: 13px;
  1213. line-height: 1.6;
  1214. li {
  1215. margin-bottom: 4px;
  1216. &:last-child {
  1217. margin-bottom: 0;
  1218. }
  1219. }
  1220. }
  1221. }
  1222. // 弹窗底部
  1223. .modal-footer {
  1224. display: flex;
  1225. justify-content: space-between;
  1226. align-items: center;
  1227. padding: 20px 28px;
  1228. background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  1229. border-top: 1px solid #e2e8f0;
  1230. border-radius: 0 0 16px 16px;
  1231. min-height: 80px;
  1232. .analysis-summary {
  1233. flex: 1;
  1234. margin-right: 20px;
  1235. .progress-indicator {
  1236. display: flex;
  1237. align-items: center;
  1238. gap: 12px;
  1239. color: #667eea;
  1240. font-weight: 600;
  1241. .spinner-small {
  1242. width: 20px;
  1243. height: 20px;
  1244. border: 2px solid #e0e7ff;
  1245. border-top-color: #667eea;
  1246. border-radius: 50%;
  1247. animation: spin 1s linear infinite;
  1248. }
  1249. }
  1250. .analysis-stats {
  1251. display: flex;
  1252. gap: 16px;
  1253. flex-wrap: wrap;
  1254. .stats-item {
  1255. font-size: 13px;
  1256. color: #64748b;
  1257. strong {
  1258. color: #475569;
  1259. font-weight: 700;
  1260. }
  1261. }
  1262. }
  1263. }
  1264. // 上传状态显示
  1265. .upload-status {
  1266. display: flex;
  1267. align-items: center;
  1268. gap: 12px;
  1269. padding: 16px;
  1270. margin: 16px 0;
  1271. border-radius: 8px;
  1272. background: #f0f9ff;
  1273. border: 1px solid #bae6fd;
  1274. &.success {
  1275. background: #f0f9f4;
  1276. border-color: #86efac;
  1277. color: #166534;
  1278. .status-icon {
  1279. color: #22c55e;
  1280. font-weight: bold;
  1281. font-size: 18px;
  1282. }
  1283. }
  1284. &.error {
  1285. background: #fef2f2;
  1286. border-color: #fca5a5;
  1287. color: #dc2626;
  1288. .status-icon {
  1289. color: #ef4444;
  1290. font-weight: bold;
  1291. font-size: 18px;
  1292. }
  1293. }
  1294. .status-icon {
  1295. display: flex;
  1296. align-items: center;
  1297. justify-content: center;
  1298. width: 24px;
  1299. height: 24px;
  1300. color: #3b82f6;
  1301. font-size: 16px;
  1302. font-weight: bold;
  1303. }
  1304. .loading-spinner {
  1305. width: 16px;
  1306. height: 16px;
  1307. border: 2px solid #e5e7eb;
  1308. border-top: 2px solid #3b82f6;
  1309. border-radius: 50%;
  1310. animation: spin 1s linear infinite;
  1311. }
  1312. .status-message {
  1313. font-size: 14px;
  1314. font-weight: 500;
  1315. }
  1316. }
  1317. .action-buttons {
  1318. display: flex;
  1319. gap: 12px;
  1320. }
  1321. .cancel-btn,
  1322. .confirm-btn {
  1323. padding: 12px 24px;
  1324. border-radius: 10px;
  1325. font-size: 14px;
  1326. font-weight: 600;
  1327. cursor: pointer;
  1328. transition: all 0.3s ease;
  1329. border: none;
  1330. outline: none;
  1331. }
  1332. .cancel-btn {
  1333. background: #f1f5f9;
  1334. color: #64748b;
  1335. border: 1px solid #cbd5e1;
  1336. &:hover {
  1337. background: #e2e8f0;
  1338. color: #475569;
  1339. }
  1340. }
  1341. .confirm-btn {
  1342. background: linear-gradient(135deg, #059669 0%, #047857 100%);
  1343. color: white;
  1344. box-shadow: 0 4px 12px rgba(5, 150, 105, 0.3);
  1345. &:hover:not(:disabled) {
  1346. transform: translateY(-2px);
  1347. box-shadow: 0 6px 16px rgba(5, 150, 105, 0.4);
  1348. }
  1349. &:disabled {
  1350. opacity: 0.5;
  1351. cursor: not-allowed;
  1352. transform: none;
  1353. box-shadow: 0 2px 4px rgba(5, 150, 105, 0.2);
  1354. }
  1355. }
  1356. }
  1357. // 动画
  1358. @keyframes fadeIn {
  1359. from {
  1360. opacity: 0;
  1361. }
  1362. to {
  1363. opacity: 1;
  1364. }
  1365. }
  1366. @keyframes slideUp {
  1367. from {
  1368. transform: translateY(30px);
  1369. opacity: 0;
  1370. }
  1371. to {
  1372. transform: translateY(0);
  1373. opacity: 1;
  1374. }
  1375. }
  1376. @keyframes slideDown {
  1377. from {
  1378. transform: translateY(-20px);
  1379. opacity: 0;
  1380. }
  1381. to {
  1382. transform: translateY(0);
  1383. opacity: 1;
  1384. }
  1385. }
  1386. @keyframes bounce {
  1387. 0%, 20%, 50%, 80%, 100% {
  1388. transform: translateY(0);
  1389. }
  1390. 40% {
  1391. transform: translateY(-8px);
  1392. }
  1393. 60% {
  1394. transform: translateY(-4px);
  1395. }
  1396. }
  1397. // 🔥 AI分析相关动画
  1398. @keyframes pulse {
  1399. 0% { transform: scale(1); }
  1400. 50% { transform: scale(1.05); }
  1401. 100% { transform: scale(1); }
  1402. }
  1403. @keyframes glow {
  1404. 0% { box-shadow: 0 0 5px rgba(24, 144, 255, 0.5); }
  1405. 50% { box-shadow: 0 0 20px rgba(24, 144, 255, 0.8); }
  1406. 100% { box-shadow: 0 0 5px rgba(24, 144, 255, 0.5); }
  1407. }
  1408. @keyframes spin {
  1409. 0% { transform: rotate(0deg); }
  1410. 100% { transform: rotate(360deg); }
  1411. }
  1412. // 特殊状态动画
  1413. .analyzing {
  1414. animation: pulse 1.5s ease-in-out infinite;
  1415. }
  1416. .completed {
  1417. animation: glow 2s ease-in-out;
  1418. }
  1419. @keyframes rotate {
  1420. from {
  1421. transform: rotate(0deg);
  1422. }
  1423. to {
  1424. transform: rotate(360deg);
  1425. }
  1426. }
  1427. @keyframes spin {
  1428. 0% { transform: rotate(0deg); }
  1429. 100% { transform: rotate(360deg); }
  1430. }
  1431. @keyframes progressMove {
  1432. 0% {
  1433. transform: translateX(-100%);
  1434. }
  1435. 50% {
  1436. transform: translateX(0%);
  1437. }
  1438. 100% {
  1439. transform: translateX(100%);
  1440. }
  1441. }
  1442. // 响应式设计
  1443. @media (max-width: 768px) {
  1444. .drag-upload-modal-container {
  1445. width: 95vw;
  1446. height: 90vh;
  1447. margin: 5vh auto;
  1448. }
  1449. .files-analysis-table {
  1450. .analysis-table {
  1451. font-size: 12px;
  1452. .col-file {
  1453. width: 80px;
  1454. }
  1455. .col-name {
  1456. width: auto;
  1457. }
  1458. .col-upload,
  1459. .col-space,
  1460. .col-stage {
  1461. width: 80px;
  1462. }
  1463. .ai-result-container {
  1464. flex-direction: column;
  1465. gap: 4px;
  1466. }
  1467. }
  1468. }
  1469. .modal-footer {
  1470. flex-direction: column;
  1471. gap: 12px;
  1472. align-items: stretch;
  1473. .analysis-summary {
  1474. margin-right: 0;
  1475. margin-bottom: 12px;
  1476. .analysis-stats {
  1477. justify-content: center;
  1478. }
  1479. }
  1480. .action-buttons {
  1481. width: 100%;
  1482. .cancel-btn,
  1483. .confirm-btn {
  1484. flex: 1;
  1485. }
  1486. }
  1487. }
  1488. }